Compare commits

..

24 Commits

Author SHA1 Message Date
ItzCrazyKns
3098622cb0 Merge branch 'pr/1082' 2026-03-27 17:53:59 +05:30
ItzCrazyKns
3646495bdf feat(ollama): update reasoning model list 2026-03-27 17:16:57 +05:30
ItzCrazyKns
476c4ec8c2 feat(app): lint & beautify 2026-03-27 01:24:04 +05:30
Nick
0e33641927 fix: handle upload errors and reset spinner state 2026-03-26 19:20:24 +00:00
ItzCrazyKns
8c061f20a5 Merge branch 'master' of https://github.com/ItzCrazyKns/Vane 2026-03-26 22:34:18 +05:30
ItzCrazyKns
72ac815294 feat(weather): change to freeipapi, move getApproxLocation to actions 2026-03-26 22:34:01 +05:30
ItzCrazyKns
d16b7e271a Delete serverUtils.ts 2026-03-26 22:20:13 +05:30
ItzCrazyKns
58ed869b3d feat(utils): move hash into utils 2026-03-26 22:19:48 +05:30
Kushagra Srivastava
3fede054da Merge pull request #1076 from saschabuehrle/fix/issue-1075
fix: guard against non-array searching queries in research steps
2026-03-26 20:35:51 +05:30
saschabuehrle
21bd88787e fix: guard against non-array searching queries in research steps (fixes #1075) 2026-03-22 18:11:17 +01:00
Kushagra Srivastava
b02f5aa37f Merge pull request #1015 from joaquinescalante23/fix/search-resilience-and-timeouts
feat: improve search resilience with timeouts and widget error handling
2026-03-10 19:05:09 +05:30
Kushagra Srivastava
f83f813bd7 Update README.md 2026-03-09 19:32:40 +05:30
ItzCrazyKns
0c101d9704 Merge branch 'master' of https://github.com/ItzCrazyKns/Vane 2026-03-09 18:48:07 +05:30
ItzCrazyKns
7ab23d6339 feat(setup-screen): fix spacing 2026-03-09 18:48:01 +05:30
Kushagra Srivastava
c42d2177b7 Merge pull request #1041 from marexxxxxxx/patch-1
fix: add typing_extensions to Dockerfile to resolve build error
2026-03-09 18:13:06 +05:30
ItzCrazyKns
39c0f198b5 feat(app): rename to 'vane' 2026-03-09 18:05:31 +05:30
Marex
80d4f23765 fix: add typing_extensions to Dockerfile to resolve build error
Add typing_extensions to the list of installed packages.
2026-03-08 22:31:22 +01:00
Joaquin
a2f2ac532e Improve resilience: catch widget execution failures 2026-03-04 10:02:51 -03:00
Joaquin
1763ee9d1f Add timeout and validation to SearXNG search 2026-03-04 10:02:51 -03:00
Kushagra Srivastava
86274326e9 Update copyright year in LICENSE file 2026-02-13 12:44:27 +05:30
Kushagra Srivastava
d7b020e5bb Update README.md 2026-01-10 23:03:58 +05:30
ItzCrazyKns
d95ff9ccdd Update docker-compose.yaml 2026-01-08 22:36:01 +05:30
ItzCrazyKns
8347b798f3 feat(app): lint & beautify 2026-01-03 23:12:19 +05:30
ItzCrazyKns
a16472bcf3 feat(actions): prevent double conversion to object array 2026-01-01 21:56:46 +05:30
40 changed files with 333 additions and 247 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

BIN
.assets/vane-screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -44,11 +44,11 @@ jobs:
DOCKERFILE=${{ matrix.variant.dockerfile }}
VARIANT=${{ matrix.variant.name }}
docker buildx build --platform linux/amd64 \
--cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-amd64 \
--cache-from=type=registry,ref=itzcrazykns1337/vane:${VARIANT}-amd64 \
--cache-to=type=inline \
--provenance false \
-f $DOCKERFILE \
-t itzcrazykns1337/perplexica:${VARIANT}-amd64 \
-t itzcrazykns1337/vane:${VARIANT}-amd64 \
--push .
- name: Build and push AMD64 Canary Docker image
@@ -57,11 +57,11 @@ jobs:
DOCKERFILE=${{ matrix.variant.dockerfile }}
VARIANT=${{ matrix.variant.name }}
docker buildx build --platform linux/amd64 \
--cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \
--cache-from=type=registry,ref=itzcrazykns1337/vane:${VARIANT}-canary-amd64 \
--cache-to=type=inline \
--provenance false \
-f $DOCKERFILE \
-t itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \
-t itzcrazykns1337/vane:${VARIANT}-canary-amd64 \
--push .
- name: Build and push AMD64 release Docker image
@@ -70,11 +70,11 @@ jobs:
DOCKERFILE=${{ matrix.variant.dockerfile }}
VARIANT=${{ matrix.variant.name }}
docker buildx build --platform linux/amd64 \
--cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
--cache-from=type=registry,ref=itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
--cache-to=type=inline \
--provenance false \
-f $DOCKERFILE \
-t itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
-t itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
--push .
build-arm64:
@@ -112,11 +112,11 @@ jobs:
DOCKERFILE=${{ matrix.variant.dockerfile }}
VARIANT=${{ matrix.variant.name }}
docker buildx build --platform linux/arm64 \
--cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-arm64 \
--cache-from=type=registry,ref=itzcrazykns1337/vane:${VARIANT}-arm64 \
--cache-to=type=inline \
--provenance false \
-f $DOCKERFILE \
-t itzcrazykns1337/perplexica:${VARIANT}-arm64 \
-t itzcrazykns1337/vane:${VARIANT}-arm64 \
--push .
- name: Build and push ARM64 Canary Docker image
@@ -125,11 +125,11 @@ jobs:
DOCKERFILE=${{ matrix.variant.dockerfile }}
VARIANT=${{ matrix.variant.name }}
docker buildx build --platform linux/arm64 \
--cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-canary-arm64 \
--cache-from=type=registry,ref=itzcrazykns1337/vane:${VARIANT}-canary-arm64 \
--cache-to=type=inline \
--provenance false \
-f $DOCKERFILE \
-t itzcrazykns1337/perplexica:${VARIANT}-canary-arm64 \
-t itzcrazykns1337/vane:${VARIANT}-canary-arm64 \
--push .
- name: Build and push ARM64 release Docker image
@@ -138,11 +138,11 @@ jobs:
DOCKERFILE=${{ matrix.variant.dockerfile }}
VARIANT=${{ matrix.variant.name }}
docker buildx build --platform linux/arm64 \
--cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 \
--cache-from=type=registry,ref=itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 \
--cache-to=type=inline \
--provenance false \
-f $DOCKERFILE \
-t itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 \
-t itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 \
--push .
manifest:
@@ -167,51 +167,51 @@ jobs:
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
run: |
VARIANT=${{ matrix.variant }}
docker manifest create itzcrazykns1337/perplexica:${VARIANT}-latest \
--amend itzcrazykns1337/perplexica:${VARIANT}-amd64 \
--amend itzcrazykns1337/perplexica:${VARIANT}-arm64
docker manifest push itzcrazykns1337/perplexica:${VARIANT}-latest
docker manifest create itzcrazykns1337/vane:${VARIANT}-latest \
--amend itzcrazykns1337/vane:${VARIANT}-amd64 \
--amend itzcrazykns1337/vane:${VARIANT}-arm64
docker manifest push itzcrazykns1337/vane:${VARIANT}-latest
if [ "$VARIANT" = "full" ]; then
docker manifest create itzcrazykns1337/perplexica:latest \
--amend itzcrazykns1337/perplexica:${VARIANT}-amd64 \
--amend itzcrazykns1337/perplexica:${VARIANT}-arm64
docker manifest push itzcrazykns1337/perplexica:latest
docker manifest create itzcrazykns1337/vane:latest \
--amend itzcrazykns1337/vane:${VARIANT}-amd64 \
--amend itzcrazykns1337/vane:${VARIANT}-arm64
docker manifest push itzcrazykns1337/vane:latest
docker manifest create itzcrazykns1337/perplexica:main \
--amend itzcrazykns1337/perplexica:${VARIANT}-amd64 \
--amend itzcrazykns1337/perplexica:${VARIANT}-arm64
docker manifest push itzcrazykns1337/perplexica:main
docker manifest create itzcrazykns1337/vane:main \
--amend itzcrazykns1337/vane:${VARIANT}-amd64 \
--amend itzcrazykns1337/vane:${VARIANT}-arm64
docker manifest push itzcrazykns1337/vane:main
fi
- name: Create and push manifest for canary
if: github.ref == 'refs/heads/canary' && github.event_name == 'push'
run: |
VARIANT=${{ matrix.variant }}
docker manifest create itzcrazykns1337/perplexica:${VARIANT}-canary \
--amend itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \
--amend itzcrazykns1337/perplexica:${VARIANT}-canary-arm64
docker manifest push itzcrazykns1337/perplexica:${VARIANT}-canary
docker manifest create itzcrazykns1337/vane:${VARIANT}-canary \
--amend itzcrazykns1337/vane:${VARIANT}-canary-amd64 \
--amend itzcrazykns1337/vane:${VARIANT}-canary-arm64
docker manifest push itzcrazykns1337/vane:${VARIANT}-canary
if [ "$VARIANT" = "full" ]; then
docker manifest create itzcrazykns1337/perplexica:canary \
--amend itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \
--amend itzcrazykns1337/perplexica:${VARIANT}-canary-arm64
docker manifest push itzcrazykns1337/perplexica:canary
docker manifest create itzcrazykns1337/vane:canary \
--amend itzcrazykns1337/vane:${VARIANT}-canary-amd64 \
--amend itzcrazykns1337/vane:${VARIANT}-canary-arm64
docker manifest push itzcrazykns1337/vane:canary
fi
- name: Create and push manifest for releases
if: github.event_name == 'release'
run: |
VARIANT=${{ matrix.variant }}
docker manifest create itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }} \
--amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
--amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64
docker manifest push itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}
docker manifest create itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }} \
--amend itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
--amend itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64
docker manifest push itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}
if [ "$VARIANT" = "full" ]; then
docker manifest create itzcrazykns1337/perplexica:${{ env.RELEASE_VERSION }} \
--amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
--amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64
docker manifest push itzcrazykns1337/perplexica:${{ env.RELEASE_VERSION }}
docker manifest create itzcrazykns1337/vane:${{ env.RELEASE_VERSION }} \
--amend itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \
--amend itzcrazykns1337/vane:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64
docker manifest push itzcrazykns1337/vane:${{ env.RELEASE_VERSION }}
fi

View File

@@ -1,12 +1,12 @@
# How to Contribute to Perplexica
# How to Contribute to Vane
Thanks for your interest in contributing to Perplexica! Your help makes this project better. This guide explains how to contribute effectively.
Thanks for your interest in contributing to Vane! Your help makes this project better. This guide explains how to contribute effectively.
Perplexica is a modern AI chat application with advanced search capabilities.
Vane is a modern AI chat application with advanced search capabilities.
## Project Structure
Perplexica's codebase is organized as follows:
Vane's codebase is organized as follows:
- **UI Components and Pages**:
- **Components (`src/components`)**: Reusable UI components.
@@ -53,7 +53,7 @@ If you are not sure where to start, use this section as a map.
## API Documentation
Perplexica includes API documentation for programmatic access.
Vane includes API documentation for programmatic access.
- **Search API**: For detailed documentation, see `docs/API/SEARCH.md`.
@@ -79,4 +79,4 @@ Before committing changes:
2. Always run `npm run format:write` to format your code according to the project's coding standards. This helps maintain consistency and code quality.
3. We currently do not have a code of conduct, but it is in the works. In the meantime, please be mindful of how you engage with the project and its community.
Following these steps will help maintain the integrity of Perplexica's codebase and facilitate a smoother integration of your valuable contributions. Thank you for your support and commitment to improving Perplexica.
Following these steps will help maintain the integrity of Vane's codebase and facilitate a smoother integration of your valuable contributions. Thank you for your support and commitment to improving Vane.

View File

@@ -2,7 +2,7 @@ FROM node:24.5.0-slim AS builder
RUN apt-get update && apt-get install -y python3 python3-pip sqlite3 && rm -rf /var/lib/apt/lists/*
WORKDIR /home/perplexica
WORKDIR /home/vane
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile --network-timeout 600000
@@ -12,7 +12,7 @@ COPY src ./src
COPY public ./public
COPY drizzle ./drizzle
RUN mkdir -p /home/perplexica/data
RUN mkdir -p /home/vane/data
RUN yarn build
FROM node:24.5.0-slim
@@ -24,15 +24,15 @@ RUN apt-get update && apt-get install -y \
curl sudo \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /home/perplexica
WORKDIR /home/vane
COPY --from=builder /home/perplexica/public ./public
COPY --from=builder /home/perplexica/.next/static ./public/_next/static
COPY --from=builder /home/perplexica/.next/standalone ./
COPY --from=builder /home/perplexica/data ./data
COPY --from=builder /home/vane/public ./public
COPY --from=builder /home/vane/.next/static ./public/_next/static
COPY --from=builder /home/vane/.next/standalone ./
COPY --from=builder /home/vane/data ./data
COPY drizzle ./drizzle
RUN mkdir /home/perplexica/uploads
RUN mkdir /home/vane/uploads
RUN useradd --shell /bin/bash --system \
--home-dir "/usr/local/searxng" \
@@ -54,13 +54,13 @@ RUN git clone "https://github.com/searxng/searxng" \
"/usr/local/searxng/searxng-src"
RUN python3 -m venv "/usr/local/searxng/searx-pyenv"
RUN "/usr/local/searxng/searx-pyenv/bin/pip" install --upgrade pip setuptools wheel pyyaml msgspec
RUN "/usr/local/searxng/searx-pyenv/bin/pip" install --upgrade pip setuptools wheel pyyaml msgspec typing_extensions
RUN cd "/usr/local/searxng/searxng-src" && \
"/usr/local/searxng/searx-pyenv/bin/pip" install --use-pep517 --no-build-isolation -e .
USER root
WORKDIR /home/perplexica
WORKDIR /home/vane
COPY entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
RUN sed -i 's/\r$//' ./entrypoint.sh || true
@@ -71,4 +71,4 @@ EXPOSE 3000 8080
ENV SEARXNG_API_URL=http://localhost:8080
CMD ["/home/perplexica/entrypoint.sh"]
CMD ["/home/vane/entrypoint.sh"]

View File

@@ -2,7 +2,7 @@ FROM node:24.5.0-slim AS builder
RUN apt-get update && apt-get install -y python3 python3-pip sqlite3 && rm -rf /var/lib/apt/lists/*
WORKDIR /home/perplexica
WORKDIR /home/vane
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile --network-timeout 600000
@@ -12,23 +12,23 @@ COPY src ./src
COPY public ./public
COPY drizzle ./drizzle
RUN mkdir -p /home/perplexica/data
RUN mkdir -p /home/vane/data
RUN yarn build
FROM node:24.5.0-slim
RUN apt-get update && apt-get install -y python3 python3-pip sqlite3 && rm -rf /var/lib/apt/lists/*
WORKDIR /home/perplexica
WORKDIR /home/vane
COPY --from=builder /home/perplexica/public ./public
COPY --from=builder /home/perplexica/.next/static ./public/_next/static
COPY --from=builder /home/vane/public ./public
COPY --from=builder /home/vane/.next/static ./public/_next/static
COPY --from=builder /home/perplexica/.next/standalone ./
COPY --from=builder /home/perplexica/data ./data
COPY --from=builder /home/vane/.next/standalone ./
COPY --from=builder /home/vane/data ./data
COPY drizzle ./drizzle
RUN mkdir /home/perplexica/uploads
RUN mkdir /home/vane/uploads
EXPOSE 3000

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2024 ItzCrazyKns
Copyright (c) 2026 ItzCrazyKns
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,18 +1,18 @@
# Perplexica 🔍
# Vane 🔍
[![GitHub Repo stars](https://img.shields.io/github/stars/ItzCrazyKns/Perplexica?style=social)](https://github.com/ItzCrazyKns/Perplexica/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/ItzCrazyKns/Perplexica?style=social)](https://github.com/ItzCrazyKns/Perplexica/network/members)
[![GitHub watchers](https://img.shields.io/github/watchers/ItzCrazyKns/Perplexica?style=social)](https://github.com/ItzCrazyKns/Perplexica/watchers)
[![Docker Pulls](https://img.shields.io/docker/pulls/itzcrazykns1337/perplexica?color=blue)](https://hub.docker.com/r/itzcrazykns1337/perplexica)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/ItzCrazyKns/Perplexica/blob/master/LICENSE)
[![GitHub last commit](https://img.shields.io/github/last-commit/ItzCrazyKns/Perplexica?color=green)](https://github.com/ItzCrazyKns/Perplexica/commits/master)
[![GitHub Repo stars](https://img.shields.io/github/stars/ItzCrazyKns/Vane?style=social)](https://github.com/ItzCrazyKns/Vane/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/ItzCrazyKns/Vane?style=social)](https://github.com/ItzCrazyKns/Vane/network/members)
[![GitHub watchers](https://img.shields.io/github/watchers/ItzCrazyKns/Vane?style=social)](https://github.com/ItzCrazyKns/Vane/watchers)
[![Docker Pulls](https://img.shields.io/docker/pulls/itzcrazykns1337/vane?color=blue)](https://hub.docker.com/r/itzcrazykns1337/vane)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/ItzCrazyKns/Vane/blob/master/LICENSE)
[![GitHub last commit](https://img.shields.io/github/last-commit/ItzCrazyKns/Vane?color=green)](https://github.com/ItzCrazyKns/Vane/commits/master)
[![Discord](https://dcbadge.limes.pink/api/server/26aArMy8tT?style=flat)](https://discord.gg/26aArMy8tT)
Perplexica is a **privacy-focused AI answering engine** that runs entirely on your own hardware. It combines knowledge from the vast internet with support for **local LLMs** (Ollama) and cloud providers (OpenAI, Claude, Groq), delivering accurate answers with **cited sources** while keeping your searches completely private.
Vane is a **privacy-focused AI answering engine** that runs entirely on your own hardware. It combines knowledge from the vast internet with support for **local LLMs** (Ollama) and cloud providers (OpenAI, Claude, Groq), delivering accurate answers with **cited sources** while keeping your searches completely private.
![preview](.assets/perplexica-screenshot.png)
![preview](.assets/vane-screenshot.png)
Want to know more about its architecture and how it works? You can read it [here](https://github.com/ItzCrazyKns/Perplexica/tree/master/docs/architecture/README.md).
Want to know more about its architecture and how it works? You can read it [here](https://github.com/ItzCrazyKns/Vane/tree/master/docs/architecture/README.md).
## ✨ Features
@@ -28,7 +28,7 @@ Want to know more about its architecture and how it works? You can read it [here
📷 **Image and video search** - Find visual content alongside text results. Search isn't limited to just articles anymore.
📄 **File uploads** - Upload documents and ask questions about them. PDFs, text files, images - Perplexica understands them all.
📄 **File uploads** - Upload documents and ask questions about them. PDFs, text files, images - Vane understands them all.
🌐 **Search specific domains** - Limit your search to specific websites when you know where to look. Perfect for technical documentation or research papers.
@@ -38,11 +38,11 @@ Want to know more about its architecture and how it works? You can read it [here
🕒 **Search history** - Every search is saved locally so you can revisit your discoveries anytime. Your research is never lost.
**More coming soon** - We're actively developing new features based on community feedback. Join our Discord to help shape Perplexica's future!
**More coming soon** - We're actively developing new features based on community feedback. Join our Discord to help shape Vane's future!
## Sponsors
Perplexica's development is powered by the generous support of our sponsors. Their contributions help keep this project free, open-source, and accessible to everyone.
Vane's development is powered by the generous support of our sponsors. Their contributions help keep this project free, open-source, and accessible to everyone.
<div align="center">
@@ -51,7 +51,7 @@ Perplexica's development is powered by the generous support of our sponsors. The
<img alt="Warp Terminal" src=".assets/sponsers/warp.png" width="100%">
</a>
### **✨ [Try Warp - The AI-Powered Terminal →](https://www.warp.dev/perplexica)**
### **✨ [Try Warp - The AI-Powered Terminal →](https://www.warp.dev/vane)**
Warp is revolutionizing development workflows with AI-powered features, modern UX, and blazing-fast performance. Used by developers at top companies worldwide.
@@ -76,26 +76,26 @@ We'd also like to thank the following partners for their generous support:
## Installation
There are mainly 2 ways of installing Perplexica - With Docker, Without Docker. Using Docker is highly recommended.
There are mainly 2 ways of installing Vane - With Docker, Without Docker. Using Docker is highly recommended.
### Getting Started with Docker (Recommended)
Perplexica can be easily run using Docker. Simply run the following command:
Vane can be easily run using Docker. Simply run the following command:
```bash
docker run -d -p 3000:3000 -v perplexica-data:/home/perplexica/data --name perplexica itzcrazykns1337/perplexica:latest
docker run -d -p 3000:3000 -v vane-data:/home/vane/data --name vane itzcrazykns1337/vane:latest
```
This will pull and start the Perplexica container with the bundled SearxNG search engine. Once running, open your browser and navigate to http://localhost:3000. You can then configure your settings (API keys, models, etc.) directly in the setup screen.
This will pull and start the Vane container with the bundled SearxNG search engine. Once running, open your browser and navigate to http://localhost:3000. You can then configure your settings (API keys, models, etc.) directly in the setup screen.
**Note**: The image includes both Perplexica and SearxNG, so no additional setup is required. The `-v` flags create persistent volumes for your data and uploaded files.
**Note**: The image includes both Vane and SearxNG, so no additional setup is required. The `-v` flags create persistent volumes for your data and uploaded files.
#### Using Perplexica with Your Own SearxNG Instance
#### Using Vane with Your Own SearxNG Instance
If you already have SearxNG running, you can use the slim version of Perplexica:
If you already have SearxNG running, you can use the slim version of Vane:
```bash
docker run -d -p 3000:3000 -e SEARXNG_API_URL=http://your-searxng-url:8080 -v perplexica-data:/home/perplexica/data --name perplexica itzcrazykns1337/perplexica:slim-latest
docker run -d -p 3000:3000 -e SEARXNG_API_URL=http://your-searxng-url:8080 -v vane-data:/home/vane/data --name vane itzcrazykns1337/vane:slim-latest
```
**Important**: Make sure your SearxNG instance has:
@@ -110,10 +110,10 @@ Replace `http://your-searxng-url:8080` with your actual SearxNG URL. Then config
If you prefer to build from source or need more control:
1. Ensure Docker is installed and running on your system.
2. Clone the Perplexica repository:
2. Clone the Vane repository:
```bash
git clone https://github.com/ItzCrazyKns/Perplexica.git
git clone https://github.com/ItzCrazyKns/Vane.git
```
3. After cloning, navigate to the directory containing the project files.
@@ -121,13 +121,13 @@ If you prefer to build from source or need more control:
4. Build and run using Docker:
```bash
docker build -t perplexica .
docker run -d -p 3000:3000 -v perplexica-data:/home/perplexica/data --name perplexica perplexica
docker build -t vane .
docker run -d -p 3000:3000 -v vane-data:/home/vane/data --name vane vane
```
5. Access Perplexica at http://localhost:3000 and configure your settings in the setup screen.
5. Access Vane at http://localhost:3000 and configure your settings in the setup screen.
**Note**: After the containers are built, you can start Perplexica directly from Docker without having to open a terminal.
**Note**: After the containers are built, you can start Vane directly from Docker without having to open a terminal.
### Non-Docker Installation
@@ -135,8 +135,8 @@ If you prefer to build from source or need more control:
2. Clone the repository:
```bash
git clone https://github.com/ItzCrazyKns/Perplexica.git
cd Perplexica
git clone https://github.com/ItzCrazyKns/Vane.git
cd Vane
```
3. Install dependencies:
@@ -161,13 +161,13 @@ If you prefer to build from source or need more control:
**Note**: Using Docker is recommended as it simplifies the setup process, especially for managing environment variables and dependencies.
See the [installation documentation](https://github.com/ItzCrazyKns/Perplexica/tree/master/docs/installation) for more information like updating, etc.
See the [installation documentation](https://github.com/ItzCrazyKns/Vane/tree/master/docs/installation) for more information like updating, etc.
### Troubleshooting
#### Local OpenAI-API-Compliant Servers
If Perplexica tells you that you haven't configured any chat model providers, ensure that:
If Vane tells you that you haven't configured any chat model providers, ensure that:
1. Your server is running on `0.0.0.0` (not `127.0.0.1`) and on the same port you put in the API URL.
2. You have specified the correct model name loaded by your local LLM server.
@@ -213,38 +213,39 @@ If you're encountering a Lemonade connection error, it is likely due to the back
## Using as a Search Engine
If you wish to use Perplexica as an alternative to traditional search engines like Google or Bing, or if you want to add a shortcut for quick access from your browser's search bar, follow these steps:
If you wish to use Vane as an alternative to traditional search engines like Google or Bing, or if you want to add a shortcut for quick access from your browser's search bar, follow these steps:
1. Open your browser's settings.
2. Navigate to the 'Search Engines' section.
3. Add a new site search with the following URL: `http://localhost:3000/?q=%s`. Replace `localhost` with your IP address or domain name, and `3000` with the port number if Perplexica is not hosted locally.
4. Click the add button. Now, you can use Perplexica directly from your browser's search bar.
3. Add a new site search with the following URL: `http://localhost:3000/?q=%s`. Replace `localhost` with your IP address or domain name, and `3000` with the port number if Vane is not hosted locally.
4. Click the add button. Now, you can use Vane directly from your browser's search bar.
## Using Perplexica's API
## Using Vane's API
Perplexica also provides an API for developers looking to integrate its powerful search engine into their own applications. You can run searches, use multiple models and get answers to your queries.
Vane also provides an API for developers looking to integrate its powerful search engine into their own applications. You can run searches, use multiple models and get answers to your queries.
For more details, check out the full documentation [here](https://github.com/ItzCrazyKns/Perplexica/tree/master/docs/API/SEARCH.md).
For more details, check out the full documentation [here](https://github.com/ItzCrazyKns/Vane/tree/master/docs/API/SEARCH.md).
## Expose Perplexica to network
## Expose Vane to network
Perplexica runs on Next.js and handles all API requests. It works right away on the same network and stays accessible even with port forwarding.
Vane runs on Next.js and handles all API requests. It works right away on the same network and stays accessible even with port forwarding.
## One-Click Deployment
[![Deploy to Sealos](https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg)](https://usw.sealos.io/?openapp=system-template%3FtemplateName%3Dperplexica)
[![Deploy to RepoCloud](https://d16t0pc4846x52.cloudfront.net/deploylobe.svg)](https://repocloud.io/details/?app_id=267)
[![Run on ClawCloud](https://raw.githubusercontent.com/ClawCloud/Run-Template/refs/heads/main/Run-on-ClawCloud.svg)](https://template.run.claw.cloud/?referralCode=U11MRQ8U9RM4&openapp=system-fastdeploy%3FtemplateName%3Dperplexica)
[![Deploy on Hostinger](https://assets.hostinger.com/vps/deploy.svg)](https://www.hostinger.com/vps/docker-hosting?compose_url=https://raw.githubusercontent.com/ItzCrazyKns/Perplexica/refs/heads/master/docker-compose.yaml)
[![Deploy on Hostinger](https://assets.hostinger.com/vps/deploy.svg)](https://www.hostinger.com/vps/docker-hosting?compose_url=https://raw.githubusercontent.com/ItzCrazyKns/Vane/refs/heads/master/docker-compose.yaml)
## Upcoming Features
- [ ] Adding more widgets, integrations, search sources
- [ ] Adding ability to create custom agents (name T.B.D.)
- [ ] Adding authentication
## Support Us
If you find Perplexica useful, consider giving us a star on GitHub. This helps more people discover Perplexica and supports the development of new features. Your support is greatly appreciated.
If you find Vane useful, consider giving us a star on GitHub. This helps more people discover Vane and supports the development of new features. Your support is greatly appreciated.
### Donations
@@ -256,10 +257,10 @@ We also accept donations to help sustain our project. If you would like to contr
## Contribution
Perplexica is built on the idea that AI and large language models should be easy for everyone to use. If you find bugs or have ideas, please share them in via GitHub Issues. For more information on contributing to Perplexica you can read the [CONTRIBUTING.md](CONTRIBUTING.md) file to learn more about Perplexica and how you can contribute to it.
Vane is built on the idea that AI and large language models should be easy for everyone to use. If you find bugs or have ideas, please share them in via GitHub Issues. For more information on contributing to Vane you can read the [CONTRIBUTING.md](CONTRIBUTING.md) file to learn more about Vane and how you can contribute to it.
## Help and Support
If you have any questions or feedback, please feel free to reach out to us. You can create an issue on GitHub or join our Discord server. There, you can connect with other users, share your experiences and reviews, and receive more personalized help. [Click here](https://discord.gg/EFwsmQDgAu) to join the Discord server. To discuss matters outside of regular support, feel free to contact me on Discord at `itzcrazykns`.
Thank you for exploring Perplexica, the AI-powered search engine designed to enhance your search experience. We are constantly working to improve Perplexica and expand its capabilities. We value your feedback and contributions which help us make Perplexica even better. Don't forget to check back for updates and new features!
Thank you for exploring Vane, the AI-powered search engine designed to enhance your search experience. We are constantly working to improve Vane and expand its capabilities. We value your feedback and contributions which help us make Vane even better. Don't forget to check back for updates and new features!

View File

@@ -1,14 +1,14 @@
services:
perplexica:
image: itzcrazykns1337/perplexica:latest
vane:
image: itzcrazykns1337/vane:latest
build:
context: .
ports:
- '3000:3000'
volumes:
- data:/home/perplexica/data
- data:/home/vane/data
restart: unless-stopped
volumes:
data:
name: 'perplexica-data'
name: 'vane-data'

View File

@@ -1,8 +1,8 @@
# Perplexica Search API Documentation
# Vane Search API Documentation
## Overview
Perplexicas Search API makes it easy to use our AI-powered search engine. You can run different types of searches, pick the models you want to use, and get the most recent info. Follow the following headings to learn more about Perplexica's search API.
Vane's Search API makes it easy to use our AI-powered search engine. You can run different types of searches, pick the models you want to use, and get the most recent info. Follow the following headings to learn more about Vane's search API.
## Endpoints
@@ -53,7 +53,7 @@ Use the `id` field as the `providerId` and the `key` field from the models array
**Full URL**: `http://localhost:3000/api/search`
**Note**: Replace `localhost:3000` with your Perplexica instance URL if running on a different host or port
**Note**: Replace `localhost:3000` with your Vane instance URL if running on a different host or port
### Request
@@ -73,12 +73,12 @@ The API accepts a JSON object in the request body, where you define the enabled
},
"optimizationMode": "speed",
"sources": ["web"],
"query": "What is Perplexica",
"query": "What is Vane",
"history": [
["human", "Hi, how are you?"],
["assistant", "I am doing well, how can I help you today?"]
],
"systemInstructions": "Focus on providing technical details about Perplexica's architecture.",
"systemInstructions": "Focus on providing technical details about Vane's architecture.",
"stream": false
}
```
@@ -115,8 +115,8 @@ The API accepts a JSON object in the request body, where you define the enabled
```json
[
["human", "What is Perplexica?"],
["assistant", "Perplexica is an AI-powered search engine..."]
["human", "What is Vane?"],
["assistant", "Vane is an AI-powered search engine..."]
]
```
@@ -130,20 +130,20 @@ The response from the API includes both the final message and the sources used t
```json
{
"message": "Perplexica is an innovative, open-source AI-powered search engine designed to enhance the way users search for information online. Here are some key features and characteristics of Perplexica:\n\n- **AI-Powered Technology**: It utilizes advanced machine learning algorithms to not only retrieve information but also to understand the context and intent behind user queries, providing more relevant results [1][5].\n\n- **Open-Source**: Being open-source, Perplexica offers flexibility and transparency, allowing users to explore its functionalities without the constraints of proprietary software [3][10].",
"message": "Vane is an innovative, open-source AI-powered search engine designed to enhance the way users search for information online. Here are some key features and characteristics of Vane:\n\n- **AI-Powered Technology**: It utilizes advanced machine learning algorithms to not only retrieve information but also to understand the context and intent behind user queries, providing more relevant results [1][5].\n\n- **Open-Source**: Being open-source, Vane offers flexibility and transparency, allowing users to explore its functionalities without the constraints of proprietary software [3][10].",
"sources": [
{
"content": "Perplexica is an innovative, open-source AI-powered search engine designed to enhance the way users search for information online.",
"content": "Vane is an innovative, open-source AI-powered search engine designed to enhance the way users search for information online.",
"metadata": {
"title": "What is Perplexica, and how does it function as an AI-powered search ...",
"url": "https://askai.glarity.app/search/What-is-Perplexica--and-how-does-it-function-as-an-AI-powered-search-engine"
"title": "What is Vane, and how does it function as an AI-powered search ...",
"url": "https://askai.glarity.app/search/What-is-Vane--and-how-does-it-function-as-an-AI-powered-search-engine"
}
},
{
"content": "Perplexica is an open-source AI-powered search tool that dives deep into the internet to find precise answers.",
"content": "Vane is an open-source AI-powered search tool that dives deep into the internet to find precise answers.",
"metadata": {
"title": "Sahar Mor's Post",
"url": "https://www.linkedin.com/posts/sahar-mor_a-new-open-source-project-called-perplexica-activity-7204489745668694016-ncja"
"url": "https://www.linkedin.com/posts/sahar-mor_a-new-open-source-project-called-vane-activity-7204489745668694016-ncja"
}
}
....
@@ -160,7 +160,7 @@ Example of streamed response objects:
```
{"type":"init","data":"Stream connected"}
{"type":"sources","data":[{"content":"...","metadata":{"title":"...","url":"..."}},...]}
{"type":"response","data":"Perplexica is an "}
{"type":"response","data":"Vane is an "}
{"type":"response","data":"innovative, open-source "}
{"type":"response","data":"AI-powered search engine..."}
{"type":"done"}

View File

@@ -1,6 +1,6 @@
# Perplexica Architecture
# Vane Architecture
Perplexica is a Next.js application that combines an AI chat experience with search.
Vane is a Next.js application that combines an AI chat experience with search.
For a high level flow, see [WORKING.md](WORKING.md). For deeper implementation details, see [CONTRIBUTING.md](../../CONTRIBUTING.md).

View File

@@ -1,6 +1,6 @@
# How Perplexica Works
# How Vane Works
This is a high level overview of how Perplexica answers a question.
This is a high level overview of how Vane answers a question.
If you want a component level overview, see [README.md](README.md).
@@ -58,7 +58,7 @@ We prompt the model to cite the references it used. The UI then renders those ci
## Search API
If you are integrating Perplexica into another product, you can call `POST /api/search`.
If you are integrating Vane into another product, you can call `POST /api/search`.
It returns:

View File

@@ -1,60 +1,60 @@
# Update Perplexica to the latest version
# Update Vane to the latest version
To update Perplexica to the latest version, follow these steps:
To update Vane to the latest version, follow these steps:
## For Docker users (Using pre-built images)
Simply pull the latest image and restart your container:
```bash
docker pull itzcrazykns1337/perplexica:latest
docker stop perplexica
docker rm perplexica
docker run -d -p 3000:3000 -v perplexica-data:/home/perplexica/data --name perplexica itzcrazykns1337/perplexica:latest
docker pull itzcrazykns1337/vane:latest
docker stop vane
docker rm vane
docker run -d -p 3000:3000 -v vane-data:/home/vane/data --name vane itzcrazykns1337/vane:latest
```
For slim version:
```bash
docker pull itzcrazykns1337/perplexica:slim-latest
docker stop perplexica
docker rm perplexica
docker run -d -p 3000:3000 -e SEARXNG_API_URL=http://your-searxng-url:8080 -v perplexica-data:/home/perplexica/data --name perplexica itzcrazykns1337/perplexica:slim-latest
docker pull itzcrazykns1337/vane:slim-latest
docker stop vane
docker rm vane
docker run -d -p 3000:3000 -e SEARXNG_API_URL=http://your-searxng-url:8080 -v vane-data:/home/vane/data --name vane itzcrazykns1337/vane:slim-latest
```
Once updated, go to http://localhost:3000 and verify the latest changes. Your settings are preserved automatically.
## For Docker users (Building from source)
1. Navigate to your Perplexica directory and pull the latest changes:
1. Navigate to your Vane directory and pull the latest changes:
```bash
cd Perplexica
cd Vane
git pull origin master
```
2. Rebuild the Docker image:
```bash
docker build -t perplexica .
docker build -t vane .
```
3. Stop and remove the old container, then start the new one:
```bash
docker stop perplexica
docker rm perplexica
docker run -p 3000:3000 -p 8080:8080 --name perplexica perplexica
docker stop vane
docker rm vane
docker run -p 3000:3000 -p 8080:8080 --name vane vane
```
4. Once the command completes, go to http://localhost:3000 and verify the latest changes.
## For non-Docker users
1. Navigate to your Perplexica directory and pull the latest changes:
1. Navigate to your Vane directory and pull the latest changes:
```bash
cd Perplexica
cd Vane
git pull origin master
```

View File

@@ -26,7 +26,7 @@ else
echo "SearXNG may not be fully ready, but continuing (PID: $SEARXNG_PID)"
fi
cd /home/perplexica
echo "Starting Perplexica..."
cd /home/vane
echo "Starting Vane..."
exec node server.js

View File

@@ -1,5 +1,5 @@
{
"name": "perplexica",
"name": "vane",
"version": "1.12.1",
"license": "MIT",
"author": "ItzCrazyKns",

View File

@@ -19,9 +19,8 @@ const montserrat = Montserrat({
});
export const metadata: Metadata = {
title: 'Perplexica - Chat with the internet',
description:
'Perplexica is an AI powered chatbot that is connected to the internet.',
title: 'Vane - Direct your curiosity',
description: 'Vane is an AI powered answering engine.',
};
export default function RootLayout({

View File

@@ -2,7 +2,7 @@ import { Metadata } from 'next';
import React from 'react';
export const metadata: Metadata = {
title: 'Library - Perplexica',
title: 'Library - Vane',
};
const Layout = ({ children }: { children: React.ReactNode }) => {

View File

@@ -2,10 +2,9 @@ import type { MetadataRoute } from 'next';
export default function manifest(): MetadataRoute.Manifest {
return {
name: 'Perplexica - Chat with the internet',
short_name: 'Perplexica',
description:
'Perplexica is an AI powered chatbot that is connected to the internet.',
name: 'Vane - Direct Your Curiosity',
short_name: 'Vane',
description: 'Vane is an AI powered answering engine.',
start_url: '/',
display: 'standalone',
background_color: '#0a0a0a',

View File

@@ -2,8 +2,8 @@ import ChatWindow from '@/components/ChatWindow';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Chat - Perplexica',
description: 'Chat with the internet, chat with Perplexica.',
title: 'Chat - Vane',
description: 'Chat with the internet, chat with Vane.',
};
const Home = () => {

View File

@@ -37,7 +37,8 @@ const getStepTitle = (
if (step.type === 'reasoning') {
return isStreaming && !step.reasoning ? 'Thinking...' : 'Thinking';
} else if (step.type === 'searching') {
return `Searching ${step.searching.length} ${step.searching.length === 1 ? 'query' : 'queries'}`;
const queries = Array.isArray(step.searching) ? step.searching : [];
return `Searching ${queries.length} ${queries.length === 1 ? 'query' : 'queries'}`;
} else if (step.type === 'search_results') {
return `Found ${step.reading.length} ${step.reading.length === 1 ? 'result' : 'results'}`;
} else if (step.type === 'reading') {
@@ -160,6 +161,7 @@ const AssistantSteps = ({
)}
{step.type === 'searching' &&
Array.isArray(step.searching) &&
step.searching.length > 0 && (
<div className="flex flex-wrap gap-1.5 mt-1.5">
{step.searching.map((query, idx) => (

View File

@@ -49,7 +49,7 @@ const Chat = () => {
};
if (messages.length === 1) {
document.title = `${messages[0].query.substring(0, 30)} - Perplexica`;
document.title = `${messages[0].query.substring(0, 30)} - Vane`;
}
if (sections.length > lastScrolledRef.current) {

View File

@@ -18,6 +18,7 @@ import { Fragment, useRef, useState } from 'react';
import { useChat } from '@/lib/hooks/useChat';
import { AnimatePresence } from 'motion/react';
import { motion } from 'framer-motion';
import { toast } from 'sonner';
const Attach = () => {
const { files, setFiles, setFileIds, fileIds } = useChat();
@@ -26,11 +27,19 @@ const Attach = () => {
const fileInputRef = useRef<any>();
const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedFiles = e.target.files;
if (!selectedFiles?.length) {
return;
}
setLoading(true);
try {
const data = new FormData();
for (let i = 0; i < e.target.files!.length; i++) {
data.append('files', e.target.files![i]);
for (let i = 0; i < selectedFiles.length; i++) {
data.append('files', selectedFiles[i]);
}
const embeddingModelProvider = localStorage.getItem(
@@ -38,19 +47,39 @@ const Attach = () => {
);
const embeddingModel = localStorage.getItem('embeddingModelKey');
data.append('embedding_model_provider_id', embeddingModelProvider!);
data.append('embedding_model_key', embeddingModel!);
if (!embeddingModelProvider || !embeddingModel) {
throw new Error('Please select an embedding model before uploading.');
}
data.append('embedding_model_provider_id', embeddingModelProvider);
data.append('embedding_model_key', embeddingModel);
const res = await fetch(`/api/uploads`, {
method: 'POST',
body: data,
});
const resData = await res.json();
const resData = await res.json().catch(() => ({}));
if (!res.ok) {
throw new Error(resData.message || 'Failed to upload file(s).');
}
if (!Array.isArray(resData.files)) {
throw new Error('Invalid upload response from server.');
}
setFiles([...files, ...resData.files]);
setFileIds([...fileIds, ...resData.files.map((file: any) => file.fileId)]);
setFileIds([
...fileIds,
...resData.files.map((file: any) => file.fileId),
]);
} catch (err: any) {
toast(err?.message || 'Failed to upload file(s).');
} finally {
setLoading(false);
e.target.value = '';
}
};
return loading ? (

View File

@@ -9,6 +9,7 @@ import { Fragment, useRef, useState } from 'react';
import { useChat } from '@/lib/hooks/useChat';
import { AnimatePresence } from 'motion/react';
import { motion } from 'framer-motion';
import { toast } from 'sonner';
const AttachSmall = () => {
const { files, setFiles, setFileIds, fileIds } = useChat();
@@ -17,11 +18,19 @@ const AttachSmall = () => {
const fileInputRef = useRef<any>();
const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedFiles = e.target.files;
if (!selectedFiles?.length) {
return;
}
setLoading(true);
try {
const data = new FormData();
for (let i = 0; i < e.target.files!.length; i++) {
data.append('files', e.target.files![i]);
for (let i = 0; i < selectedFiles.length; i++) {
data.append('files', selectedFiles[i]);
}
const embeddingModelProvider = localStorage.getItem(
@@ -29,19 +38,39 @@ const AttachSmall = () => {
);
const embeddingModel = localStorage.getItem('embeddingModelKey');
data.append('embedding_model_provider_id', embeddingModelProvider!);
data.append('embedding_model_key', embeddingModel!);
if (!embeddingModelProvider || !embeddingModel) {
throw new Error('Please select an embedding model before uploading.');
}
data.append('embedding_model_provider_id', embeddingModelProvider);
data.append('embedding_model_key', embeddingModel);
const res = await fetch(`/api/uploads`, {
method: 'POST',
body: data,
});
const resData = await res.json();
const resData = await res.json().catch(() => ({}));
if (!res.ok) {
throw new Error(resData.message || 'Failed to upload file(s).');
}
if (!Array.isArray(resData.files)) {
throw new Error('Invalid upload response from server.');
}
setFiles([...files, ...resData.files]);
setFileIds([...fileIds, ...resData.files.map((file: any) => file.fileId)]);
setFileIds([
...fileIds,
...resData.files.map((file: any) => file.fileId),
]);
} catch (err: any) {
toast(err?.message || 'Failed to upload file(s).');
} finally {
setLoading(false);
e.target.value = '';
}
};
return loading ? (

View File

@@ -154,7 +154,7 @@ const SettingsDialogue = ({
Version: {process.env.NEXT_PUBLIC_VERSION}
</p>
<a
href="https://github.com/itzcrazykns/perplexica"
href="https://github.com/itzcrazykns/vane"
target="_blank"
rel="noopener noreferrer"
className="text-xs text-black/70 dark:text-white/70 flex flex-row space-x-1 items-center transition duration-200 hover:text-black/90 hover:dark:text-white/90"

View File

@@ -46,9 +46,9 @@ const SetupWizard = ({
animate={{ opacity: 1, translateY: '0px' }}
className="text-4xl md:text-6xl xl:text-8xl font-normal font-['Instrument_Serif'] tracking-tight"
>
Welcome to{' '}
Welcome to
<span className="text-[#24A0ED] italic font-['PP_Editorial']">
Perplexica
Vane
</span>
</motion.h2>
<motion.p
@@ -91,9 +91,9 @@ const SetupWizard = ({
}}
className="text-2xl md:text-4xl xl:text-6xl font-normal font-['Instrument_Serif'] tracking-tight"
>
Let us get{' '}
Let us get
<span className="text-[#24A0ED] italic font-['PP_Editorial']">
Perplexica
Vane
</span>{' '}
set up for you
</motion.p>

View File

@@ -1,5 +1,8 @@
import { Cloud, Sun, CloudRain, CloudSnow, Wind } from 'lucide-react';
'use client';
import { Wind } from 'lucide-react';
import { useEffect, useState } from 'react';
import { getApproxLocation } from '@/lib/actions';
const WeatherWidget = () => {
const [data, setData] = useState({
@@ -15,17 +18,6 @@ const WeatherWidget = () => {
const [loading, setLoading] = useState(true);
const getApproxLocation = async () => {
const res = await fetch('https://ipwhois.app/json/');
const data = await res.json();
return {
latitude: data.latitude,
longitude: data.longitude,
city: data.city,
};
};
const getLocation = async (
callback: (location: {
latitude: number;

View File

@@ -1,12 +1,4 @@
export const getSuggestions = async (chatHistory: [string, string][]) => {
const chatTurns = chatHistory.map(([role, content]) => {
if (role === 'human') {
return { role: 'user', content };
} else {
return { role: 'assistant', content };
}
});
const chatModel = localStorage.getItem('chatModelKey');
const chatModelProvider = localStorage.getItem('chatModelProviderId');
@@ -16,7 +8,7 @@ export const getSuggestions = async (chatHistory: [string, string][]) => {
'Content-Type': 'application/json',
},
body: JSON.stringify({
chatHistory: chatTurns,
chatHistory,
chatModel: {
providerId: chatModelProvider,
key: chatModel,
@@ -28,3 +20,17 @@ export const getSuggestions = async (chatHistory: [string, string][]) => {
return data.suggestions;
};
export const getApproxLocation = async () => {
const res = await fetch('https://free.freeipapi.com/api/json', {
method: 'GET',
});
const data = await res.json();
return {
latitude: data.latitude,
longitude: data.longitude,
city: data.cityName,
};
};

View File

@@ -19,6 +19,9 @@ class APISearchAgent {
chatHistory: input.chatHistory,
followUp: input.followUp,
llm: input.config.llm,
}).catch((err) => {
console.error(`Error executing widgets: ${err}`);
return [];
});
let searchPromise: Promise<ResearcherOutput> | null = null;

View File

@@ -30,7 +30,9 @@ const academicSearchAction: ResearchAction<typeof schema> = {
config.classification.classification.skipSearch === false &&
config.classification.classification.academicSearch === true,
execute: async (input, additionalConfig) => {
input.queries = input.queries.slice(0, 3);
input.queries = (
Array.isArray(input.queries) ? input.queries : [input.queries]
).slice(0, 3);
const researchBlock = additionalConfig.session.getBlock(
additionalConfig.researchBlockId,

View File

@@ -30,7 +30,9 @@ const socialSearchAction: ResearchAction<typeof schema> = {
config.classification.classification.skipSearch === false &&
config.classification.classification.discussionSearch === true,
execute: async (input, additionalConfig) => {
input.queries = input.queries.slice(0, 3);
input.queries = (
Array.isArray(input.queries) ? input.queries : [input.queries]
).slice(0, 3);
const researchBlock = additionalConfig.session.getBlock(
additionalConfig.researchBlockId,

View File

@@ -85,7 +85,9 @@ const webSearchAction: ResearchAction<typeof actionSchema> = {
config.sources.includes('web') &&
config.classification.classification.skipSearch === false,
execute: async (input, additionalConfig) => {
input.queries = input.queries.slice(0, 3);
input.queries = (
Array.isArray(input.queries) ? input.queries : [input.queries]
).slice(0, 3);
const researchBlock = additionalConfig.session.getBlock(
additionalConfig.researchBlockId,

View File

@@ -90,7 +90,7 @@ const weatherWidget: Widget = {
const locationRes = await fetch(openStreetMapUrl, {
headers: {
'User-Agent': 'Perplexica',
'User-Agent': 'Vane',
'Content-Type': 'application/json',
},
});
@@ -109,7 +109,7 @@ const weatherWidget: Widget = {
`https://api.open-meteo.com/v1/forecast?latitude=${location.lat}&longitude=${location.lon}&current=temperature_2m,relative_humidity_2m,apparent_temperature,is_day,precipitation,rain,showers,snowfall,weather_code,cloud_cover,pressure_msl,surface_pressure,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max&timezone=auto&forecast_days=7`,
{
headers: {
'User-Agent': 'Perplexica',
'User-Agent': 'Vane',
'Content-Type': 'application/json',
},
},
@@ -143,7 +143,7 @@ const weatherWidget: Widget = {
`https://api.open-meteo.com/v1/forecast?latitude=${params.lat}&longitude=${params.lon}&current=temperature_2m,relative_humidity_2m,apparent_temperature,is_day,precipitation,rain,showers,snowfall,weather_code,cloud_cover,pressure_msl,surface_pressure,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max&timezone=auto&forecast_days=7`,
{
headers: {
'User-Agent': 'Perplexica',
'User-Agent': 'Vane',
'Content-Type': 'application/json',
},
},
@@ -152,7 +152,7 @@ const weatherWidget: Widget = {
`https://nominatim.openstreetmap.org/reverse?lat=${params.lat}&lon=${params.lon}&format=json`,
{
headers: {
'User-Agent': 'Perplexica',
'User-Agent': 'Vane',
'Content-Type': 'application/json',
},
},

View File

@@ -3,7 +3,6 @@ import { suggestionGeneratorPrompt } from '@/lib/prompts/suggestions';
import { ChatTurnMessage } from '@/lib/types';
import z from 'zod';
import BaseLLM from '@/lib/models/base/llm';
import { i } from 'mathjs';
type SuggestionGeneratorInput = {
chatHistory: ChatTurnMessage[];

View File

@@ -1,7 +1,7 @@
import path from 'node:path';
import fs from 'fs';
import { Config, ConfigModelProvider, UIConfigSections } from './types';
import { hashObj } from '../serverUtils';
import { hashObj } from '../utils/hash';
import { getModelProvidersUIConfigSection } from '../models/providers';
class ConfigManager {

View File

@@ -25,7 +25,9 @@ const reasoningModels = [
'qwen3',
'deepseek-v3.1',
'magistral',
'nemotron-3-nano',
'nemotron-3',
'nemotron-cascade-2',
'glm-4.7-flash',
];
class OllamaLLM extends BaseLLM<OllamaConfig> {

View File

@@ -4,7 +4,7 @@ export const getWriterPrompt = (
mode: 'speed' | 'balanced' | 'quality',
) => {
return `
You are Perplexica, an AI model skilled in web search and crafting detailed, engaging, and well-structured answers. You excel at summarizing web pages and extracting relevant information to create professional, blog-style responses.
You are Vane, an AI model skilled in web search and crafting detailed, engaging, and well-structured answers. You excel at summarizing web pages and extracting relevant information to create professional, blog-style responses.
Your task is to provide answers that are:
- **Informative and relevant**: Thoroughly address the user's query using the given context.

View File

@@ -38,11 +38,30 @@ export const searchSearxng = async (
});
}
const res = await fetch(url);
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000);
try {
const res = await fetch(url, {
signal: controller.signal,
});
if (!res.ok) {
throw new Error(`SearXNG error: ${res.statusText}`);
}
const data = await res.json();
const results: SearxngSearchResult[] = data.results;
const suggestions: string[] = data.suggestions;
return { results, suggestions };
} catch (err: any) {
if (err.name === 'AbortError') {
throw new Error('SearXNG search timed out');
}
throw err;
} finally {
clearTimeout(timeoutId);
}
};

1
src/lib/serverActions.ts Normal file
View File

@@ -0,0 +1 @@
'use server';

View File

@@ -2,8 +2,7 @@ import BaseEmbedding from "../models/base/embedding";
import UploadManager from "./manager";
import computeSimilarity from "../utils/computeSimilarity";
import { Chunk } from "../types";
import { hashObj } from "../serverUtils";
import fs from 'fs';
import { hashObj } from '../utils/hash';
type UploadStoreParams = {
embeddingModel: BaseEmbedding<any>;