Compare commits

...

11 Commits

Author SHA1 Message Date
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
ItzCrazyKns
3b8d8be676 feat(package): bump version 2025-12-31 12:58:59 +05:30
ItzCrazyKns
b83f9bac78 feat(providers): extract/repair json before parsing 2025-12-31 12:58:24 +05:30
ItzCrazyKns
bd7c563137 feat(package): add json repair 2025-12-31 12:57:59 +05:30
ItzCrazyKns
23b903db9a Update searxng.ts 2025-12-30 22:16:06 +05:30
ItzCrazyKns
a98f0df83f feat(app): lint & beautify 2025-12-29 22:02:21 +05:30
ItzCrazyKns
164d528761 feat(compose): add build context, remove uploads 2025-12-28 13:11:05 +05:30
ItzCrazyKns
af4ec17117 Update docker-compose.yaml 2025-12-28 12:49:25 +05:30
11 changed files with 30 additions and 19 deletions

View File

@@ -240,6 +240,7 @@ Perplexica runs on Next.js and handles all API requests. It works right away on
## Upcoming Features ## Upcoming Features
- [ ] Adding more widgets, integrations, search sources - [ ] Adding more widgets, integrations, search sources
- [ ] Adding ability to create custom agents (name T.B.D.)
- [ ] Adding authentication - [ ] Adding authentication
## Support Us ## Support Us

View File

@@ -7,11 +7,8 @@ services:
- '3000:3000' - '3000:3000'
volumes: volumes:
- data:/home/perplexica/data - data:/home/perplexica/data
- uploads:/home/perplexica/uploads
restart: unless-stopped restart: unless-stopped
volumes: volumes:
data: data:
name: 'perplexica-data' name: 'perplexica-data'
uploads:
name: 'perplexica-uploads'

2
next-env.d.ts vendored
View File

@@ -1,6 +1,6 @@
/// <reference types="next" /> /// <reference types="next" />
/// <reference types="next/image-types/global" /> /// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts"; import './.next/dev/types/routes.d.ts';
// NOTE: This file should not be edited // NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -1,6 +1,6 @@
{ {
"name": "perplexica", "name": "perplexica",
"version": "1.12.0", "version": "1.12.1",
"license": "MIT", "license": "MIT",
"author": "ItzCrazyKns", "author": "ItzCrazyKns",
"scripts": { "scripts": {
@@ -19,6 +19,7 @@
"@phosphor-icons/react": "^2.1.10", "@phosphor-icons/react": "^2.1.10",
"@radix-ui/react-tooltip": "^1.2.8", "@radix-ui/react-tooltip": "^1.2.8",
"@tailwindcss/typography": "^0.5.12", "@tailwindcss/typography": "^0.5.12",
"@toolsycc/json-repair": "^0.1.22",
"axios": "^1.8.3", "axios": "^1.8.3",
"better-sqlite3": "^11.9.1", "better-sqlite3": "^11.9.1",
"clsx": "^2.1.0", "clsx": "^2.1.0",

View File

@@ -80,7 +80,10 @@ const Chat = () => {
{loading && !messageAppeared && <MessageBoxLoading />} {loading && !messageAppeared && <MessageBoxLoading />}
<div ref={messageEnd} className="h-0" /> <div ref={messageEnd} className="h-0" />
{dividerWidth > 0 && ( {dividerWidth > 0 && (
<div className="fixed z-40 bottom-24 lg:bottom-6" style={{ width: dividerWidth }}> <div
className="fixed z-40 bottom-24 lg:bottom-6"
style={{ width: dividerWidth }}
>
<div <div
className="pointer-events-none absolute -bottom-6 left-0 right-0 h-[calc(100%+24px+24px)] dark:hidden" className="pointer-events-none absolute -bottom-6 left-0 right-0 h-[calc(100%+24px+24px)] dark:hidden"
style={{ style={{

View File

@@ -1,12 +1,4 @@
export const getSuggestions = async (chatHistory: [string, string][]) => { 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 chatModel = localStorage.getItem('chatModelKey');
const chatModelProvider = localStorage.getItem('chatModelProviderId'); const chatModelProvider = localStorage.getItem('chatModelProviderId');
@@ -16,7 +8,7 @@ export const getSuggestions = async (chatHistory: [string, string][]) => {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
chatHistory: chatTurns, chatHistory,
chatModel: { chatModel: {
providerId: chatModelProvider, providerId: chatModelProvider,
key: chatModel, key: chatModel,

View File

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

View File

@@ -11,6 +11,7 @@ import { Ollama, Tool as OllamaTool, Message as OllamaMessage } from 'ollama';
import { parse } from 'partial-json'; import { parse } from 'partial-json';
import crypto from 'crypto'; import crypto from 'crypto';
import { Message } from '@/lib/types'; import { Message } from '@/lib/types';
import { repairJson } from '@toolsycc/json-repair';
type OllamaConfig = { type OllamaConfig = {
baseURL: string; baseURL: string;
@@ -205,7 +206,13 @@ class OllamaLLM extends BaseLLM<OllamaConfig> {
}); });
try { try {
return input.schema.parse(JSON.parse(response.message.content)) as T; return input.schema.parse(
JSON.parse(
repairJson(response.message.content, {
extractJson: true,
}) as string,
),
) as T;
} catch (err) { } catch (err) {
throw new Error(`Error parsing response from Ollama: ${err}`); throw new Error(`Error parsing response from Ollama: ${err}`);
} }

View File

@@ -18,6 +18,7 @@ import {
ChatCompletionToolMessageParam, ChatCompletionToolMessageParam,
} from 'openai/resources/index.mjs'; } from 'openai/resources/index.mjs';
import { Message } from '@/lib/types'; import { Message } from '@/lib/types';
import { repairJson } from '@toolsycc/json-repair';
type OpenAIConfig = { type OpenAIConfig = {
apiKey: string; apiKey: string;
@@ -213,7 +214,13 @@ class OpenAILLM extends BaseLLM<OpenAIConfig> {
if (response.choices && response.choices.length > 0) { if (response.choices && response.choices.length > 0) {
try { try {
return input.schema.parse(response.choices[0].message.parsed) as T; return input.schema.parse(
JSON.parse(
repairJson(response.choices[0].message.content!, {
extractJson: true,
}) as string,
),
) as T;
} catch (err) { } catch (err) {
throw new Error(`Error parsing response from OpenAI: ${err}`); throw new Error(`Error parsing response from OpenAI: ${err}`);
} }

View File

@@ -1,4 +1,3 @@
import axios from 'axios';
import { getSearxngURL } from './config/serverRegistry'; import { getSearxngURL } from './config/serverRegistry';
interface SearxngSearchOptions { interface SearxngSearchOptions {

View File

@@ -1384,6 +1384,11 @@
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==
"@toolsycc/json-repair@^0.1.22":
version "0.1.22"
resolved "https://registry.yarnpkg.com/@toolsycc/json-repair/-/json-repair-0.1.22.tgz#7ad0eb30c4ef1c4286ad3487dc1bbda562f09986"
integrity sha512-IMrsxovS9a5pWGRxMCDQDW8FKKEZI/yK/HMcyJlbnd/s+Mk0dRtGr1BFicL276gDsPvb/JfNHtHSi1oc0eY1jA==
"@types/better-sqlite3@^7.6.12": "@types/better-sqlite3@^7.6.12":
version "7.6.12" version "7.6.12"
resolved "https://registry.yarnpkg.com/@types/better-sqlite3/-/better-sqlite3-7.6.12.tgz#e5712d46d71097dcc2775c0b068072eadc15deb7" resolved "https://registry.yarnpkg.com/@types/better-sqlite3/-/better-sqlite3-7.6.12.tgz#e5712d46d71097dcc2775c0b068072eadc15deb7"