mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-07 13:23:15 +00:00
Merge branch 'master' of github.com:khoj-ai/khoj into features/new-sign-in-page
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Noto_Sans } from "next/font/google";
|
||||
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||
import "../globals.css";
|
||||
|
||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
||||
import { ContentSecurityPolicy } from "../common/layoutHelper";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Khoj AI - Agents",
|
||||
@@ -33,20 +32,9 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<meta
|
||||
httpEquiv="Content-Security-Policy"
|
||||
content="default-src 'self' https://assets.khoj.dev;
|
||||
media-src * blob:;
|
||||
script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval';
|
||||
connect-src 'self' https://ipapi.co/json ws://localhost:42110;
|
||||
style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com;
|
||||
img-src 'self' data: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com;
|
||||
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
|
||||
child-src 'none';
|
||||
object-src 'none';"
|
||||
></meta>
|
||||
<body className={inter.className}>{children}</body>
|
||||
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||
<ContentSecurityPolicy />
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Metadata } from "next";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
|
||||
import "../globals.css";
|
||||
import { ContentSecurityPolicy } from "../common/layoutHelper";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Khoj AI - Automations",
|
||||
@@ -32,9 +33,12 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<div>
|
||||
{children}
|
||||
<Toaster />
|
||||
</div>
|
||||
<html>
|
||||
<ContentSecurityPolicy />
|
||||
<body>
|
||||
{children}
|
||||
<Toaster />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -994,7 +994,7 @@ export default function Automations() {
|
||||
const [suggestedAutomations, setSuggestedAutomations] = useState<AutomationsData[]>([]);
|
||||
const [showLoginPrompt, setShowLoginPrompt] = useState(false);
|
||||
const isMobileWidth = useIsMobileWidth();
|
||||
const ipLocationData = useIPLocationData();
|
||||
const { locationData, locationDataError, locationDataLoading } = useIPLocationData();
|
||||
|
||||
useEffect(() => {
|
||||
if (newAutomationData) {
|
||||
@@ -1044,18 +1044,18 @@ export default function Automations() {
|
||||
{authenticatedData.email}
|
||||
</span>
|
||||
) : null}
|
||||
{ipLocationData && (
|
||||
{locationData && (
|
||||
<span className="rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm">
|
||||
<MapPinSimple className="h-4 w-4 mr-2 inline text-purple-500" />
|
||||
{ipLocationData
|
||||
? `${ipLocationData.city}, ${ipLocationData.country}`
|
||||
{locationData
|
||||
? `${locationData.city}, ${locationData.country}`
|
||||
: "Unknown"}
|
||||
</span>
|
||||
)}
|
||||
{ipLocationData && (
|
||||
{locationData && (
|
||||
<span className="rounded-lg text-sm border-secondary border p-1 flex items-center shadow-sm">
|
||||
<Clock className="h-4 w-4 mr-2 inline text-green-500" />
|
||||
{ipLocationData ? `${ipLocationData.timezone}` : "Unknown"}
|
||||
{locationData ? `${locationData.timezone}` : "Unknown"}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -1086,7 +1086,7 @@ export default function Automations() {
|
||||
setNewAutomationData={setNewAutomationData}
|
||||
authenticatedData={authenticatedData}
|
||||
isCreating={isCreating}
|
||||
ipLocationData={ipLocationData}
|
||||
ipLocationData={locationData}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
@@ -1103,7 +1103,7 @@ export default function Automations() {
|
||||
<SharedAutomationCard
|
||||
isMobileWidth={isMobileWidth}
|
||||
authenticatedData={authenticatedData}
|
||||
locationData={ipLocationData}
|
||||
locationData={locationData}
|
||||
isLoggedIn={authenticatedData ? true : false}
|
||||
setShowLoginPrompt={setShowLoginPrompt}
|
||||
setNewAutomationData={setNewAutomationData}
|
||||
@@ -1125,7 +1125,7 @@ export default function Automations() {
|
||||
setNewAutomationData={setNewAutomationData}
|
||||
authenticatedData={authenticatedData}
|
||||
isCreating={isCreating}
|
||||
ipLocationData={ipLocationData}
|
||||
ipLocationData={locationData}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
@@ -1147,7 +1147,7 @@ export default function Automations() {
|
||||
key={automation.id}
|
||||
authenticatedData={authenticatedData}
|
||||
automation={automation}
|
||||
locationData={ipLocationData}
|
||||
locationData={locationData}
|
||||
isLoggedIn={authenticatedData ? true : false}
|
||||
setShowLoginPrompt={setShowLoginPrompt}
|
||||
/>
|
||||
@@ -1158,7 +1158,7 @@ export default function Automations() {
|
||||
key={automation.id}
|
||||
authenticatedData={authenticatedData}
|
||||
automation={automation}
|
||||
locationData={ipLocationData}
|
||||
locationData={locationData}
|
||||
isLoggedIn={authenticatedData ? true : false}
|
||||
setShowLoginPrompt={setShowLoginPrompt}
|
||||
/>
|
||||
@@ -1173,7 +1173,7 @@ export default function Automations() {
|
||||
key={automation.id}
|
||||
authenticatedData={authenticatedData}
|
||||
automation={automation}
|
||||
locationData={ipLocationData}
|
||||
locationData={locationData}
|
||||
isLoggedIn={authenticatedData ? true : false}
|
||||
setShowLoginPrompt={setShowLoginPrompt}
|
||||
suggestedCard={true}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Noto_Sans } from "next/font/google";
|
||||
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||
import "../globals.css";
|
||||
|
||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
||||
import { ContentSecurityPolicy } from "../common/layoutHelper";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Khoj AI - Chat",
|
||||
@@ -34,20 +33,9 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<meta
|
||||
httpEquiv="Content-Security-Policy"
|
||||
content="default-src 'self' https://assets.khoj.dev;
|
||||
media-src * blob:;
|
||||
script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval';
|
||||
connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110;
|
||||
style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com;
|
||||
img-src 'self' data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com;
|
||||
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
|
||||
child-src 'none';
|
||||
object-src 'none';"
|
||||
></meta>
|
||||
<body className={inter.className}>
|
||||
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||
<ContentSecurityPolicy />
|
||||
<body>
|
||||
{children}
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
|
||||
@@ -184,8 +184,10 @@ export default function Chat() {
|
||||
useState<AbortController | null>(null);
|
||||
const [triggeredAbort, setTriggeredAbort] = useState(false);
|
||||
|
||||
const locationData = useIPLocationData() || {
|
||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
const { locationData, locationDataError, locationDataLoading } = useIPLocationData() || {
|
||||
locationData: {
|
||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
},
|
||||
};
|
||||
const authenticatedData = useAuthenticatedData();
|
||||
const isMobileWidth = useIsMobileWidth();
|
||||
@@ -239,9 +241,13 @@ export default function Chat() {
|
||||
|
||||
useEffect(() => {
|
||||
if (processQuerySignal) {
|
||||
if (locationDataLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
chat();
|
||||
}
|
||||
}, [processQuerySignal]);
|
||||
}, [processQuerySignal, locationDataLoading]);
|
||||
|
||||
async function readChatStream(response: Response) {
|
||||
if (!response.ok) throw new Error(response.statusText);
|
||||
@@ -380,7 +386,7 @@ export default function Chat() {
|
||||
<title>
|
||||
{`${defaultTitle}${!!title && title !== defaultTitle ? `: ${title}` : ""}`}
|
||||
</title>
|
||||
<div>
|
||||
<div className={isMobileWidth ? "h-1" : "h-auto"}>
|
||||
<SidePanel
|
||||
conversationId={conversationId}
|
||||
uploadedFiles={[]}
|
||||
@@ -389,9 +395,9 @@ export default function Chat() {
|
||||
</div>
|
||||
<div className={styles.chatBox}>
|
||||
<div className={styles.chatBoxBody}>
|
||||
{!isMobileWidth && conversationId && (
|
||||
{conversationId && (
|
||||
<div
|
||||
className={`${styles.chatTitleWrapper} text-nowrap text-ellipsis overflow-hidden max-w-screen-md grid items-top font-bold mr-8 pt-6 col-auto h-fit`}
|
||||
className={`${styles.chatTitleWrapper} text-nowrap text-ellipsis overflow-hidden max-w-screen-md grid items-top font-bold mx-2 md:mr-8 md:pt-6 col-auto h-fit`}
|
||||
>
|
||||
{title && (
|
||||
<h2
|
||||
@@ -403,7 +409,7 @@ export default function Chat() {
|
||||
<ChatSessionActionMenu
|
||||
conversationId={conversationId}
|
||||
setTitle={setTitle}
|
||||
sizing="md"
|
||||
sizing={isMobileWidth ? "sm" : "md"}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface UserProfile {
|
||||
is_active: boolean;
|
||||
has_documents: boolean;
|
||||
detail: string;
|
||||
khoj_version: string;
|
||||
}
|
||||
|
||||
const fetcher = (url: string) =>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AttachedFileText } from "../components/chatInputArea/chatInputArea";
|
||||
import {
|
||||
CodeContext,
|
||||
Context,
|
||||
@@ -16,6 +17,12 @@ export interface MessageMetadata {
|
||||
turnId: string;
|
||||
}
|
||||
|
||||
export interface GeneratedAssetsData {
|
||||
images: string[];
|
||||
excalidrawDiagram: string;
|
||||
files: AttachedFileText[];
|
||||
}
|
||||
|
||||
export interface ResponseWithIntent {
|
||||
intentType: string;
|
||||
response: string;
|
||||
@@ -84,6 +91,8 @@ export function processMessageChunk(
|
||||
|
||||
if (!currentMessage || !chunk || !chunk.type) return { context, onlineContext, codeContext };
|
||||
|
||||
console.log(`chunk type: ${chunk.type}`);
|
||||
|
||||
if (chunk.type === "status") {
|
||||
console.log(`status: ${chunk.data}`);
|
||||
const statusMessage = chunk.data as string;
|
||||
@@ -98,6 +107,20 @@ export function processMessageChunk(
|
||||
} else if (chunk.type === "metadata") {
|
||||
const messageMetadata = chunk.data as MessageMetadata;
|
||||
currentMessage.turnId = messageMetadata.turnId;
|
||||
} else if (chunk.type === "generated_assets") {
|
||||
const generatedAssets = chunk.data as GeneratedAssetsData;
|
||||
|
||||
if (generatedAssets.images) {
|
||||
currentMessage.generatedImages = generatedAssets.images;
|
||||
}
|
||||
|
||||
if (generatedAssets.excalidrawDiagram) {
|
||||
currentMessage.generatedExcalidrawDiagram = generatedAssets.excalidrawDiagram;
|
||||
}
|
||||
|
||||
if (generatedAssets.files) {
|
||||
currentMessage.generatedFiles = generatedAssets.files;
|
||||
}
|
||||
} else if (chunk.type === "message") {
|
||||
const chunkData = chunk.data;
|
||||
// Here, handle if the response is a JSON response with an image, but the intentType is excalidraw
|
||||
|
||||
@@ -51,6 +51,7 @@ import {
|
||||
FilePdf,
|
||||
FileMd,
|
||||
MicrosoftWordLogo,
|
||||
Microscope,
|
||||
} from "@phosphor-icons/react";
|
||||
import { OrgMode } from "@/app/components/logo/fileLogo";
|
||||
|
||||
@@ -219,6 +220,10 @@ export function getIconForSlashCommand(command: string, customClassName: string
|
||||
return <Code className={className} />;
|
||||
}
|
||||
|
||||
if (command.includes("research")) {
|
||||
return <Microscope className={className} />;
|
||||
}
|
||||
|
||||
return <ArrowRight className={className} />;
|
||||
}
|
||||
|
||||
|
||||
16
src/interface/web/app/common/layoutHelper.tsx
Normal file
16
src/interface/web/app/common/layoutHelper.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
export function ContentSecurityPolicy() {
|
||||
return (
|
||||
<meta
|
||||
httpEquiv="Content-Security-Policy"
|
||||
content="default-src 'self' https://assets.khoj.dev;
|
||||
media-src * blob:;
|
||||
script-src 'self' https://assets.khoj.dev https://app.chatwoot.com 'unsafe-inline' 'unsafe-eval';
|
||||
connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110;
|
||||
style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com;
|
||||
img-src 'self' data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com;
|
||||
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
|
||||
child-src 'self' https://app.chatwoot.com;
|
||||
object-src 'none';"
|
||||
></meta>
|
||||
);
|
||||
}
|
||||
@@ -23,32 +23,30 @@ export function welcomeConsole() {
|
||||
`%c %s`,
|
||||
"font-family:monospace",
|
||||
`
|
||||
__ __ __ __ ______ __ _____ __
|
||||
/\\ \\/ / /\\ \\_\\ \\ /\\ __ \\ /\\ \\ /\\ __ \\ /\\ \\
|
||||
\\ \\ _"-. \\ \\ __ \\ \\ \\ \\/\\ \\ _\\_\\ \\ \\ \\ __ \\ \\ \\ \\
|
||||
\\ \\_\\ \\_\\ \\ \\_\\ \\_\\ \\ \\_____\\ /\\_____\\ \\ \\_\\ \\_\\ \\ \\_\\
|
||||
\\/_/\\/_/ \\/_/\\/_/ \\/_____/ \\/_____/ \\/_/\\/_/ \\/_/
|
||||
__ __ __ __ ______ __ _____ __
|
||||
/\\ \\/ / /\\ \\_\\ \\ /\\ __ \\ /\\ \\ /\\ __ \\ /\\ \\
|
||||
\\ \\ _"-. \\ \\ __ \\ \\ \\ \\/\\ \\ _\\_\\ \\ \\ \\ __ \\ \\ \\ \\
|
||||
\\ \\_\\ \\_\\ \\ \\_\\ \\_\\ \\ \\_____\\ /\\_____\\ \\ \\_\\ \\_\\ \\ \\_\\
|
||||
\\/_/\\/_/ \\/_/\\/_/ \\/_____/ \\/_____/ \\/_/\\/_/ \\/_/
|
||||
|
||||
|
||||
Greetings traveller,
|
||||
Greetings traveller,
|
||||
|
||||
I am ✨Khoj✨, your open-source, personal AI copilot.
|
||||
I am ✨Khoj✨, your open-source, personal AI copilot.
|
||||
|
||||
See my source code at https://github.com/khoj-ai/khoj
|
||||
Read my operating manual at https://docs.khoj.dev
|
||||
`,
|
||||
See my source code at https://github.com/khoj-ai/khoj
|
||||
Read my operating manual at https://docs.khoj.dev
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
export function useIPLocationData() {
|
||||
const { data: locationData, error: locationDataError } = useSWR<LocationData>(
|
||||
"/api/ip",
|
||||
locationFetcher,
|
||||
{ revalidateOnFocus: false },
|
||||
);
|
||||
|
||||
if (locationDataError || !locationData) return;
|
||||
return locationData;
|
||||
const {
|
||||
data: locationData,
|
||||
error: locationDataError,
|
||||
isLoading: locationDataLoading,
|
||||
} = useSWR<LocationData>("/api/ip", locationFetcher, { revalidateOnFocus: false });
|
||||
return { locationData, locationDataError, locationDataLoading };
|
||||
}
|
||||
|
||||
export function useIsMobileWidth() {
|
||||
|
||||
@@ -54,6 +54,12 @@ function TrainOfThoughtComponent(props: TrainOfThoughtComponentProps) {
|
||||
const lastIndex = props.trainOfThought.length - 1;
|
||||
const [collapsed, setCollapsed] = useState(props.completed);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.completed) {
|
||||
setCollapsed(true);
|
||||
}
|
||||
}, [props.completed]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${!collapsed ? styles.trainOfThought + " shadow-sm" : ""}`}
|
||||
@@ -410,6 +416,9 @@ export default function ChatHistory(props: ChatHistoryProps) {
|
||||
"inferred-queries": message.inferredQueries || [],
|
||||
},
|
||||
conversationId: props.conversationId,
|
||||
images: message.generatedImages,
|
||||
queryFiles: message.generatedFiles,
|
||||
excalidrawDiagram: message.generatedExcalidrawDiagram,
|
||||
turnId: messageTurnId,
|
||||
}}
|
||||
conversationId={props.conversationId}
|
||||
|
||||
@@ -77,6 +77,21 @@ div.imageWrapper img {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
div.khoj div.imageWrapper img {
|
||||
height: 512px;
|
||||
}
|
||||
|
||||
div.khoj div.imageWrapper {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
div.khoj div.imagesContainer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
div.chatMessageContainer > img {
|
||||
width: auto;
|
||||
height: auto;
|
||||
@@ -178,4 +193,9 @@ div.trainOfThoughtElement ul {
|
||||
div.youfullHistory {
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
div.khoj div.imageWrapper img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@ export interface SingleChatMessage {
|
||||
conversationId: string;
|
||||
turnId?: string;
|
||||
queryFiles?: AttachedFileText[];
|
||||
excalidrawDiagram?: string;
|
||||
}
|
||||
|
||||
export interface StreamMessage {
|
||||
@@ -180,6 +181,10 @@ export interface StreamMessage {
|
||||
inferredQueries?: string[];
|
||||
turnId?: string;
|
||||
queryFiles?: AttachedFileText[];
|
||||
excalidrawDiagram?: string;
|
||||
generatedFiles?: AttachedFileText[];
|
||||
generatedImages?: string[];
|
||||
generatedExcalidrawDiagram?: string;
|
||||
}
|
||||
|
||||
export interface ChatHistoryData {
|
||||
@@ -264,6 +269,9 @@ interface ChatMessageProps {
|
||||
onDeleteMessage: (turnId?: string) => void;
|
||||
conversationId: string;
|
||||
turnId?: string;
|
||||
generatedImage?: string;
|
||||
excalidrawDiagram?: string;
|
||||
generatedFiles?: AttachedFileText[];
|
||||
}
|
||||
|
||||
interface TrainOfThoughtProps {
|
||||
@@ -389,9 +397,8 @@ const ChatMessage = forwardRef<HTMLDivElement, ChatMessageProps>((props, ref) =>
|
||||
// Prepare initial message for rendering
|
||||
let message = props.chatMessage.message;
|
||||
|
||||
if (props.chatMessage.intent && props.chatMessage.intent.type == "excalidraw") {
|
||||
message = props.chatMessage.intent["inferred-queries"][0];
|
||||
setExcalidrawData(props.chatMessage.message);
|
||||
if (props.chatMessage.excalidrawDiagram) {
|
||||
setExcalidrawData(props.chatMessage.excalidrawDiagram);
|
||||
}
|
||||
|
||||
// Replace LaTeX delimiters with placeholders
|
||||
@@ -401,27 +408,6 @@ const ChatMessage = forwardRef<HTMLDivElement, ChatMessageProps>((props, ref) =>
|
||||
.replace(/\\\[/g, "LEFTBRACKET")
|
||||
.replace(/\\\]/g, "RIGHTBRACKET");
|
||||
|
||||
const intentTypeHandlers = {
|
||||
"text-to-image": (msg: string) => ``,
|
||||
"text-to-image2": (msg: string) => ``,
|
||||
"text-to-image-v3": (msg: string) =>
|
||||
``,
|
||||
excalidraw: (msg: string) => msg,
|
||||
};
|
||||
|
||||
// Handle intent-specific rendering
|
||||
if (props.chatMessage.intent) {
|
||||
const { type, "inferred-queries": inferredQueries } = props.chatMessage.intent;
|
||||
|
||||
if (type in intentTypeHandlers) {
|
||||
message = intentTypeHandlers[type as keyof typeof intentTypeHandlers](message);
|
||||
}
|
||||
|
||||
if (type.includes("text-to-image") && inferredQueries?.length > 0) {
|
||||
message += `\n\n${inferredQueries[0]}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace file links with base64 data
|
||||
message = renderCodeGenImageInline(message, props.chatMessage.codeContext);
|
||||
|
||||
|
||||
35
src/interface/web/app/components/chatWoot/ChatwootWidget.tsx
Normal file
35
src/interface/web/app/components/chatWoot/ChatwootWidget.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
"use client";
|
||||
|
||||
import Script from "next/script";
|
||||
|
||||
export function ChatwootWidget() {
|
||||
return (
|
||||
<Script
|
||||
id="chatwoot-widget"
|
||||
strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
window.chatwootSettings = {
|
||||
position: "right",
|
||||
type: "standard",
|
||||
launcherTitle: "Chat with us"
|
||||
};
|
||||
(function(d,t) {
|
||||
var BASE_URL="https://app.chatwoot.com";
|
||||
var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
|
||||
g.src=BASE_URL+"/packs/js/sdk.js";
|
||||
g.defer = true;
|
||||
g.async = true;
|
||||
s.parentNode.insertBefore(g,s);
|
||||
g.onload=function(){
|
||||
window.chatwootSDK.run({
|
||||
websiteToken: '5uV59Ay2pvMJenJary2hvvVM',
|
||||
baseUrl: BASE_URL
|
||||
})
|
||||
}
|
||||
})(document,"script");
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ div.settingsMenuOptions {
|
||||
grid-auto-flow: row;
|
||||
position: absolute;
|
||||
background-color: var(--background-color);
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
||||
top: 64px;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
@@ -69,6 +69,6 @@ div.settingsMenuOptions {
|
||||
}
|
||||
|
||||
div.titleBar {
|
||||
padding: 8px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Moon, Sun, UserCircle, Question, GearFine, ArrowRight } from "@phosphor-icons/react";
|
||||
import { Moon, Sun, UserCircle, Question, GearFine, ArrowRight, Code } from "@phosphor-icons/react";
|
||||
import { KhojAgentLogo, KhojAutomationLogo, KhojSearchLogo } from "../logo/khojLogo";
|
||||
import { useIsMobileWidth } from "@/app/common/utils";
|
||||
|
||||
@@ -37,6 +37,15 @@ function SubscriptionBadge({ is_active }: { is_active: boolean }) {
|
||||
);
|
||||
}
|
||||
|
||||
function VersionBadge({ version }: { version: string }) {
|
||||
return (
|
||||
<div className="flex flex-row items-center">
|
||||
<div className="w-3 h-3 rounded-full bg-green-500 mr-1"></div>
|
||||
<p className="text-xs">{version}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function NavMenu() {
|
||||
const userData = useAuthenticatedData();
|
||||
const [darkMode, setDarkMode] = useState(false);
|
||||
@@ -99,6 +108,9 @@ export default function NavMenu() {
|
||||
<div className="flex flex-col">
|
||||
<p className="font-semibold">{userData?.email}</p>
|
||||
<SubscriptionBadge is_active={userData?.is_active ?? false} />
|
||||
{userData?.khoj_version && (
|
||||
<VersionBadge version={userData?.khoj_version} />
|
||||
)}
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
@@ -143,18 +155,18 @@ export default function NavMenu() {
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{userData && (
|
||||
<DropdownMenuItem>
|
||||
<Link href="/settings" className="no-underline w-full">
|
||||
<div className="flex flex-rows">
|
||||
<GearFine className="w-6 h-6" />
|
||||
<p className="ml-3 font-semibold">Settings</p>
|
||||
</div>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
{userData && (
|
||||
<DropdownMenuItem>
|
||||
<Link href="/settings" className="no-underline w-full">
|
||||
<div className="flex flex-rows">
|
||||
<GearFine className="w-6 h-6" />
|
||||
<p className="ml-3 font-semibold">Settings</p>
|
||||
</div>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem>
|
||||
<Link href="https://docs.khoj.dev" className="no-underline w-full">
|
||||
<div className="flex flex-rows">
|
||||
@@ -163,6 +175,17 @@ export default function NavMenu() {
|
||||
</div>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Link
|
||||
href="https://github.com/khoj-ai/khoj/releases"
|
||||
className="no-underline w-full"
|
||||
>
|
||||
<div className="flex flex-rows">
|
||||
<Code className="w-6 h-6" />
|
||||
<p className="ml-3 font-semibold">Releases</p>
|
||||
</div>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
{userData ? (
|
||||
<DropdownMenuItem>
|
||||
<Link href="/auth/logout" className="no-underline w-full">
|
||||
@@ -207,6 +230,9 @@ export default function NavMenu() {
|
||||
<div className="flex flex-col">
|
||||
<p className="font-semibold">{userData?.email}</p>
|
||||
<SubscriptionBadge is_active={userData?.is_active ?? false} />
|
||||
{userData?.khoj_version && (
|
||||
<VersionBadge version={userData?.khoj_version} />
|
||||
)}
|
||||
</div>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator className="dark:bg-white height-[2px] bg-black" />
|
||||
@@ -251,6 +277,16 @@ export default function NavMenu() {
|
||||
</Link>
|
||||
</MenubarItem>
|
||||
)}
|
||||
{userData && (
|
||||
<MenubarItem>
|
||||
<Link href="/settings" className="no-underline w-full">
|
||||
<div className="flex flex-rows">
|
||||
<GearFine className="w-6 h-6" />
|
||||
<p className="ml-3 font-semibold">Settings</p>
|
||||
</div>
|
||||
</Link>
|
||||
</MenubarItem>
|
||||
)}
|
||||
<>
|
||||
<MenubarSeparator className="dark:bg-white height-[2px] bg-black" />
|
||||
<MenubarItem>
|
||||
@@ -264,16 +300,18 @@ export default function NavMenu() {
|
||||
</div>
|
||||
</Link>
|
||||
</MenubarItem>
|
||||
{userData && (
|
||||
<MenubarItem>
|
||||
<Link href="/settings" className="no-underline w-full">
|
||||
<div className="flex flex-rows">
|
||||
<GearFine className="w-6 h-6" />
|
||||
<p className="ml-3 font-semibold">Settings</p>
|
||||
</div>
|
||||
</Link>
|
||||
</MenubarItem>
|
||||
)}
|
||||
|
||||
<MenubarItem>
|
||||
<Link
|
||||
href="https://github.com/khoj-ai/khoj/releases"
|
||||
className="no-underline w-full"
|
||||
>
|
||||
<div className="flex flex-rows">
|
||||
<Code className="w-6 h-6" />
|
||||
<p className="ml-3 font-semibold">Releases</p>
|
||||
</div>
|
||||
</Link>
|
||||
</MenubarItem>
|
||||
{userData ? (
|
||||
<MenubarItem>
|
||||
<Link href="/auth/logout" className="no-underline w-full">
|
||||
|
||||
@@ -105,7 +105,6 @@ import { ScrollAreaScrollbar } from "@radix-ui/react-scroll-area";
|
||||
import { KhojLogoType } from "@/app/components/logo/khojLogo";
|
||||
import NavMenu from "@/app/components/navMenu/navMenu";
|
||||
import { getIconFromIconName } from "@/app/common/iconUtils";
|
||||
import AgentProfileCard from "../profileCard/profileCard";
|
||||
|
||||
// Define a fetcher function
|
||||
const fetcher = (url: string) =>
|
||||
@@ -627,43 +626,56 @@ export function ChatSessionActionMenu(props: ChatSessionActionMenuProps) {
|
||||
const size = sizeClass();
|
||||
|
||||
return (
|
||||
<DropdownMenu onOpenChange={(open) => setIsOpen(open)} open={isOpen}>
|
||||
<DropdownMenuTrigger>
|
||||
<DotsThreeVertical className={`${size}`} />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
className="p-0 text-sm h-auto"
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsRenaming(true)}
|
||||
>
|
||||
<Pencil className={`mr-2 ${size}`} />
|
||||
Rename
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
className="p-0 text-sm h-auto"
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsSharing(true)}
|
||||
>
|
||||
<Share className={`mr-2 ${size}`} />
|
||||
Share
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
className="p-0 text-sm h-auto text-rose-300 hover:text-rose-400"
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsDeleting(true)}
|
||||
>
|
||||
<Trash className={`mr-2 ${size}`} />
|
||||
Delete
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<div className="flex items-center gap-2">
|
||||
{(props.sizing === "lg" || props.sizing === "md") && (
|
||||
<Button
|
||||
className="p-0 text-sm h-auto"
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsSharing(true)}
|
||||
>
|
||||
<Share className={`${size}`} />
|
||||
</Button>
|
||||
)}
|
||||
<DropdownMenu onOpenChange={(open) => setIsOpen(open)} open={isOpen}>
|
||||
<DropdownMenuTrigger>
|
||||
<DotsThreeVertical className={`${size}`} />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
className="p-0 text-sm h-auto"
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsRenaming(true)}
|
||||
>
|
||||
<Pencil className={`mr-2 ${size}`} />
|
||||
Rename
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
{props.sizing === "sm" && (
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
className="p-0 text-sm h-auto"
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsSharing(true)}
|
||||
>
|
||||
<Share className={`mr-2 ${size}`} />
|
||||
Share
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
className="p-0 text-sm h-auto text-rose-300 hover:text-rose-400"
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsDeleting(true)}
|
||||
>
|
||||
<Trash className={`mr-2 ${size}`} />
|
||||
Delete
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -685,7 +697,11 @@ function ChatSession(props: ChatHistory) {
|
||||
>
|
||||
<p className={styles.session}>{title}</p>
|
||||
</Link>
|
||||
<ChatSessionActionMenu conversationId={props.conversation_id} setTitle={setTitle} />
|
||||
<ChatSessionActionMenu
|
||||
conversationId={props.conversation_id}
|
||||
setTitle={setTitle}
|
||||
sizing="sm"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -726,7 +742,6 @@ function ChatSessionsModal({ data, showSidePanel }: ChatSessionsModalProps) {
|
||||
}
|
||||
});
|
||||
});
|
||||
console.log(agentNameToStyleMapLocal);
|
||||
setAgentNameToStyleMap(agentNameToStyleMapLocal);
|
||||
setAgentOptions(agents);
|
||||
}
|
||||
@@ -950,7 +965,7 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
}}
|
||||
>
|
||||
<DrawerTrigger>
|
||||
<Sidebar className="h-8 w-8 mx-2" weight="thin" />
|
||||
<Sidebar className="h-6 w-6 mx-2" weight="thin" />
|
||||
</DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<DrawerHeader>
|
||||
@@ -1022,7 +1037,7 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
</div>
|
||||
)}
|
||||
{props.isMobileWidth && (
|
||||
<Link href="/" className="content-center">
|
||||
<Link href="/" className="content-center h-fit self-center">
|
||||
<KhojLogoType />
|
||||
</Link>
|
||||
)}
|
||||
|
||||
@@ -724,12 +724,6 @@ export const suggestionsData: Suggestion[] = [
|
||||
description: "Draw a diagram illustrating the structure of the United States government.",
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
type: SuggestionType.Health,
|
||||
color: suggestionToColorMap[SuggestionType.Health] || DEFAULT_COLOR,
|
||||
description: "Draw a diagram of the human skeletal system.",
|
||||
link: "",
|
||||
},
|
||||
{
|
||||
type: SuggestionType.Code,
|
||||
color: suggestionToColorMap[SuggestionType.Code] || DEFAULT_COLOR,
|
||||
|
||||
13
src/interface/web/app/fonts.ts
Normal file
13
src/interface/web/app/fonts.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Noto_Sans, Noto_Sans_Arabic } from "next/font/google";
|
||||
|
||||
export const noto_sans = Noto_Sans({
|
||||
subsets: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "devanagari", "vietnamese"],
|
||||
display: "swap",
|
||||
variable: "--font-noto-sans",
|
||||
});
|
||||
|
||||
export const noto_sans_arabic = Noto_Sans_Arabic({
|
||||
subsets: ["arabic"],
|
||||
display: "swap",
|
||||
variable: "--font-noto-sans-arabic",
|
||||
});
|
||||
@@ -1,7 +1,6 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@100..900&family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap");
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
@@ -25,7 +24,7 @@
|
||||
--input: 220 13% 91%;
|
||||
--ring: 24.6 95% 53.1%;
|
||||
--radius: 0.5rem;
|
||||
--font-family: "Noto Sans", "Noto Sans Arabic", sans-serif !important;
|
||||
--font-family: var(--font-noto-sans), var(--font-noto-sans-arabic), sans-serif !important;
|
||||
|
||||
/* Khoj Custom Colors */
|
||||
--frosted-background-color: 20 13% 95%;
|
||||
@@ -188,7 +187,7 @@
|
||||
--border: 0 0% 9%;
|
||||
--input: 0 0% 9%;
|
||||
--ring: 20.5 90.2% 48.2%;
|
||||
--font-family: "Noto Sans", "Noto Sans Arabic", sans-serif !important;
|
||||
--font-family: var(--font-noto-sans), var(--font-noto-sans-arabic), sans-serif !important;
|
||||
|
||||
/* Imported from highlight.js */
|
||||
pre code.hljs {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Noto_Sans } from "next/font/google";
|
||||
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||
import "./globals.css";
|
||||
|
||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
||||
import { ContentSecurityPolicy } from "./common/layoutHelper";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Khoj AI - Home",
|
||||
@@ -39,20 +38,9 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
{/* <meta
|
||||
httpEquiv="Content-Security-Policy"
|
||||
content="default-src 'self' https://assets.khoj.dev;
|
||||
media-src * blob:;
|
||||
script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval';
|
||||
connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110;
|
||||
style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com;
|
||||
img-src 'self' data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com;
|
||||
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
|
||||
child-src 'none';
|
||||
object-src 'none';"
|
||||
></meta> */}
|
||||
<body className={inter.className}>{children}</body>
|
||||
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||
<ContentSecurityPolicy />
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
import "../globals.css";
|
||||
import { ContentSecurityPolicy } from "../common/layoutHelper";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Khoj AI - Search",
|
||||
@@ -31,5 +32,10 @@ export default function RootLayout({
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return <div>{children}</div>;
|
||||
return (
|
||||
<html>
|
||||
<ContentSecurityPolicy />
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Noto_Sans } from "next/font/google";
|
||||
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||
import "../globals.css";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
|
||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
||||
import { ContentSecurityPolicy } from "../common/layoutHelper";
|
||||
import { ChatwootWidget } from "../components/chatWoot/ChatwootWidget";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Khoj AI - Settings",
|
||||
@@ -34,21 +34,12 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<meta
|
||||
httpEquiv="Content-Security-Policy"
|
||||
content="default-src 'self' https://assets.khoj.dev;
|
||||
script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval';
|
||||
connect-src 'self' https://ipapi.co/json ws://localhost:42110;
|
||||
style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com;
|
||||
img-src 'self' data: https://*.khoj.dev https://*.googleusercontent.com;
|
||||
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
|
||||
child-src 'none';
|
||||
object-src 'none';"
|
||||
></meta>
|
||||
<body className={inter.className}>
|
||||
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||
<ContentSecurityPolicy />
|
||||
<body>
|
||||
{children}
|
||||
<Toaster />
|
||||
<ChatwootWidget />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Noto_Sans } from "next/font/google";
|
||||
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||
import "../../globals.css";
|
||||
|
||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
||||
import { ContentSecurityPolicy } from "@/app/common/layoutHelper";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Khoj AI - Chat",
|
||||
@@ -15,19 +14,9 @@ export default function RootLayout({
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<meta
|
||||
httpEquiv="Content-Security-Policy"
|
||||
content="default-src 'self' https://assets.khoj.dev;
|
||||
script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval';
|
||||
connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110;
|
||||
style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com;
|
||||
img-src 'self' data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com;
|
||||
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
|
||||
child-src 'none';
|
||||
object-src 'none';"
|
||||
></meta>
|
||||
<body className={inter.className}>
|
||||
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||
<ContentSecurityPolicy />
|
||||
<body>
|
||||
{children}
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "khoj-ai",
|
||||
"version": "1.30.1",
|
||||
"version": "1.31.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -62,6 +62,9 @@
|
||||
"react-hook-form": "^7.52.1",
|
||||
"shadcn-ui": "^0.8.0",
|
||||
"swr": "^2.2.5",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss": "^3.4.6",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript": "^5",
|
||||
"vaul": "^0.9.1",
|
||||
"zod": "^3.23.8"
|
||||
@@ -82,9 +85,6 @@
|
||||
"lint-staged": "^15.2.7",
|
||||
"nodemon": "^3.1.3",
|
||||
"prettier": "3.3.3",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss": "^3.4.6",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"prettier": {
|
||||
|
||||
100
src/interface/web/public/assets/icons/khoj_lantern.svg
Normal file
100
src/interface/web/public/assets/icons/khoj_lantern.svg
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="200"
|
||||
height="200"
|
||||
viewBox="0 0 200 200"
|
||||
className="fill-zinc-950 dark:fill-zinc-300"
|
||||
version="1.1"
|
||||
id="svg14"
|
||||
sodipodi:docname="khoj.svg"
|
||||
inkscape:export-filename="khoj_lantern_512x512.png"
|
||||
inkscape:export-xdpi="245.75999"
|
||||
inkscape:export-ydpi="245.75999"
|
||||
inkscape:version="1.3 (0e150ed, 2023-07-21)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview14"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.18"
|
||||
inkscape:cx="99.576271"
|
||||
inkscape:cy="77.542373"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="1022"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg14"
|
||||
inkscape:export-bgcolor="#ffffffe0" />
|
||||
<g
|
||||
clipPath="url(#clip0_45_75)"
|
||||
id="g14"
|
||||
transform="matrix(1.0349659,0,0,1.0429132,13.551981,6.7616199)">
|
||||
<!-- Fire -->
|
||||
<path
|
||||
d="m 57.9394,93.0404 9.6002,-43.9341 c 1.2591,0.4205 4.1969,2.8379 7.1871,2.8379 3.7772,0 4.5116,-4.5196 11.4364,-6.1487 5.5084,-1.3138 10.1773,-0.3679 12.9053,1.8394 0,0 0.6295,5.991 2.0986,7.7778 1.364,1.6291 3.462,1.051 3.462,1.051 3.043,14.3469 9.443,44.1973 10.65,48.7693 1.521,5.728 -4.355,8.881 -6.61,14.136 -2.256,5.256 -14.427,7.515 -21.6141,8.251 -7.187,0.736 -27.3319,-7.988 -29.1155,-10.405 -1.7837,-2.418 -2.5706,-7.358 -2.8329,-12.035 -0.2623,-3.731 1.7837,-9.6696 2.8329,-12.1396 z"
|
||||
fill="#fae80b"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 57.9394,92.9879 4.3542,-18.1833 c 1.259,0.4205 4.669,-1.3663 9.1806,-5.7282 2.6755,-2.6276 8.3936,-10.1952 14.584,-13.7163 4.5116,-2.5751 8.8658,-1.1561 11.5413,1.0511 0,0 2.4135,1.2087 5.2465,1.2087 2.098,0 1.783,-1.2087 1.783,-1.2087 3.043,14.3469 9.443,44.1968 10.65,48.7688 1.521,5.728 -4.355,8.882 -6.61,14.137 -2.256,5.255 -14.427,7.515 -21.6141,8.251 -7.187,0.735 -27.3319,-7.988 -29.1155,-10.406 -1.7837,-2.417 -2.5706,-7.357 -2.8329,-12.034 -0.2623,-3.679 1.7837,-9.6176 2.8329,-12.1401 z"
|
||||
fill="#ffcc09"
|
||||
id="path2" />
|
||||
<path
|
||||
d="m 69.3233,123.731 c -10.3347,-2.627 -13.4299,-14.662 -13.6922,-20.338 3.1476,3.206 11.4889,9.407 19.5153,8.566 10.0724,-1.051 17.5743,-5.097 25.7056,-11.456 8.131,-6.3064 13.692,-3.3109 13.692,6.306 0,9.617 -6.925,11.299 -9.023,15.661 -2.098,4.414 -23.24,4.572 -36.1977,1.261 z"
|
||||
fill="#fba719"
|
||||
id="path3" />
|
||||
<!-- Lamp -->
|
||||
<path
|
||||
d="m 46.6374,143.679 c -3.0428,0 -5.351,-0.841 -6.9773,-2.575 -2.9378,-3.1 -2.1509,-7.725 -2.0984,-7.935 0.1573,-0.894 14.7414,-89.2874 16.1053,-97.9586 1.2591,-8.0406 10.3872,-9.8274 15.0562,-9.6172 l -0.1049,3.1532 c -0.0525,0 -2.8853,-0.1051 -5.7707,0.7883 -3.5673,1.1036 -5.6132,3.1531 -6.0854,6.1487 -1.3115,8.6712 -15.948,97.1176 -16.1054,98.0106 0,0.053 -0.5246,3.311 1.3116,5.256 1.3115,1.366 3.5148,1.839 6.6624,1.418 l 0.3673,3.101 c -0.7869,0.158 -1.5738,0.21 -2.3607,0.21 z"
|
||||
id="path4" />
|
||||
<path
|
||||
d="m 106.023,33.371 h -3.095 c 0.052,-0.1577 0.052,-0.3679 0.052,-0.5255 V 15.2403 c 0,-1.7343 -1.416,-3.1532 -3.1476,-3.1532 H 89.4977 c 1.3639,-1.2087 2.2558,-2.99549 2.2558,-4.99249 0,-3.67869 -2.9903,-6.6742 -6.6625,-6.6742 -3.6722,0 -6.6625,2.99551 -6.6625,6.6742 0,1.997 0.8394,3.78379 2.2558,4.99249 h -9.8626 c -1.7312,0 -3.1476,1.4189 -3.1476,3.1532 v 17.6052 c 0,0.2102 0,0.3678 0.0524,0.5255 h -3.6722 c -2.4656,0 -4.5116,2.0495 -4.5116,4.5195 0,2.5226 2.046,4.5196 4.5116,4.5196 h 42.0207 c 2.466,0 4.512,-2.0496 4.512,-4.5196 -0.053,-2.5225 -2.046,-4.5195 -4.564,-4.5195 z M 85.0385,3.52103 c 1.941,0 3.5149,1.57657 3.5149,3.52102 0,1.94446 -1.5739,3.52105 -3.5149,3.52105 -1.941,0 -3.5148,-1.57659 -3.5148,-3.52105 0,-1.94445 1.5738,-3.52102 3.5148,-3.52102 z"
|
||||
id="path5" />
|
||||
<path
|
||||
d="m 123.177,143.679 c -0.734,0 -1.521,-0.052 -2.361,-0.157 l 0.368,-3.101 c 3.147,0.42 5.351,-0.105 6.662,-1.419 1.836,-1.944 1.312,-5.203 1.312,-5.203 -0.158,-0.893 -14.794,-89.3394 -16.106,-98.0106 -0.472,-2.9955 -2.518,-5.0451 -6.085,-6.1487 -2.885,-0.8934 -5.718,-0.7883 -5.771,-0.7883 l -0.105,-3.1531 c 4.669,-0.2102 13.85,1.5766 15.056,9.6171 1.312,8.6712 15.948,97.0646 16.106,97.9586 0.052,0.157 0.839,4.782 -2.099,7.883 -1.626,1.629 -3.934,2.522 -6.977,2.522 z"
|
||||
id="path6" />
|
||||
<path
|
||||
d="m 122.443,151.142 -0.053,-21.337 c 0,-5.045 -12.748,-9.774 -12.748,-9.774 h -0.209 c -4.407,4.309 -11.8565,7.409 -24.1847,7.409 -12.3282,0 -19.7252,-3.1 -24.1843,-7.409 h -0.2099 c 0,0 -12.7478,4.729 -12.7478,9.774 0,5.045 0,21.337 0,21.337 0,0 -5.9281,3.836 -5.9281,8.303 0,4.467 0,7.725 0,7.725 0,0 5.0362,10.984 43.0701,10.984 h 0.0524 c 38.0343,0 43.0703,-10.984 43.0703,-10.984 0,0 0,-3.258 0,-7.725 0,-4.467 -5.928,-8.303 -5.928,-8.303 z"
|
||||
id="path7" />
|
||||
<path
|
||||
d="m 117.931,87.658 c -1.206,-2.4174 -4.511,-7.1472 -5.875,-9.0916 l -8.132,-37.4176 -2.833,0.6307 11.647,53.4461 0.052,0.1577 c 0,0.0525 0.472,1.4714 0.84,3.6787 -0.578,0.5255 -1.26,0.998 -2.046,1.471 -3.253,1.945 -14.7943,5.361 -26.2831,8.461 -11.4364,-3.1 -22.9253,-6.516 -26.1778,-8.461 -0.8394,-0.525 -1.5738,-1.0506 -2.2034,-1.6287 0.3673,-2.1547 0.7869,-3.521 0.8394,-3.5736 V 95.2782 L 69.4053,41.5167 66.5725,40.886 58.3362,79.0394 c -1.5214,2.1546 -4.4592,6.4114 -5.5608,8.6712 -0.9443,1.8919 -1.9935,6.8318 1.259,11.1412 -0.7869,4.8872 -1.0492,12.9282 3.7247,19.5492 5.0362,6.99 14.2693,10.511 27.4893,10.511 13.2201,0 22.4536,-3.521 27.4896,-10.511 4.721,-6.569 4.511,-14.452 3.777,-19.339 3.515,-4.4145 2.413,-9.4595 1.416,-11.404 z m -1.836,0.946 c 0.63,1.3138 1.364,4.3618 -0.105,7.4099 -0.21,-0.7883 -0.367,-1.2613 -0.419,-1.4715 l -2.309,-10.5631 c 1.102,1.6817 2.256,3.4685 2.833,4.6247 z m -61.431,0 c 0.5246,-1.0511 1.4688,-2.5751 2.518,-4.1517 l -2.2033,10.0376 c -0.0525,0.1576 -0.2098,0.5781 -0.3672,1.2087 -1.2066,-2.943 -0.5246,-5.8334 0.0525,-7.0946 z m 1.9934,12.77 c 0.4197,0.316 0.9443,0.631 1.4165,0.946 3.0427,1.84 12.9053,4.835 23.24,7.725 -10.7544,2.891 -20.4596,5.256 -21.8761,5.624 -2.8853,-4.73 -3.1476,-10.196 -2.7804,-14.295 z m 28.6435,24.595 c -11.6463,0 -19.8825,-2.838 -24.4991,-8.461 3.305,-0.788 13.7447,-3.416 24.5515,-6.359 10.5971,2.89 20.9847,5.466 24.4467,6.359 -4.617,5.623 -12.8529,8.461 -24.4991,8.461 z m 25.8101,-10.3 c -1.941,-0.473 -11.3835,-2.838 -21.7707,-5.624 10.3872,-2.89 20.2497,-5.938 23.3447,-7.777 0.472,-0.263 0.84,-0.526 1.259,-0.841 0.367,4.099 0.053,9.564 -2.833,14.242 z"
|
||||
id="path8" />
|
||||
<path
|
||||
d="m 39.188,44.7224 c -0.3147,0 -0.577,-0.1051 -0.8393,-0.2627 l -14.0594,-9.88 c -0.682,-0.4729 -0.8394,-1.3663 -0.3673,-2.0495 0.4722,-0.6832 1.364,-0.8409 2.046,-0.3679 l 14.0594,9.8799 c 0.682,0.473 0.8394,1.3664 0.3672,2.0496 -0.3147,0.4204 -0.7344,0.6306 -1.2066,0.6306 z"
|
||||
id="path9" />
|
||||
<path
|
||||
d="M 18.8334,80.6685 1.67885,80.6159 c -0.786909,0 -1.468889,-0.6306 -1.468889,-1.4714 0,-0.8409 0.629519,-1.4715 1.468889,-1.4715 l 17.15455,0.0525 c 0.7869,0 1.4689,0.6307 1.4689,1.4715 0,0.8409 -0.682,1.4715 -1.4689,1.4715 z"
|
||||
id="path10" />
|
||||
<path
|
||||
d="m 13.2726,128.754 c -0.4722,0 -0.9443,-0.21 -1.2066,-0.683 -0.4197,-0.683 -0.2098,-1.576 0.4197,-1.997 l 14.4266,-9.249 c 0.682,-0.421 1.5738,-0.263 1.9935,0.42 0.4197,0.683 0.2099,1.577 -0.4197,1.997 l -14.4266,9.25 c -0.2098,0.157 -0.4721,0.262 -0.7869,0.262 z"
|
||||
id="path11" />
|
||||
<path
|
||||
d="m 130.889,43.6188 c -0.472,0 -0.892,-0.2102 -1.207,-0.6307 -0.472,-0.6831 -0.314,-1.5765 0.368,-2.0495 l 14.059,-9.8799 c 0.629,-0.473 1.574,-0.3154 2.046,0.3678 0.472,0.6832 0.315,1.5766 -0.367,2.0496 l -14.06,9.8799 c -0.262,0.1577 -0.524,0.2628 -0.839,0.2628 z"
|
||||
id="path12" />
|
||||
<path
|
||||
d="m 151.244,79.5649 c -0.787,0 -1.469,-0.6306 -1.469,-1.4715 0,-0.7883 0.629,-1.4715 1.469,-1.4715 l 17.154,-0.0525 c 0.787,0 1.469,0.6306 1.469,1.4715 0,0.7883 -0.629,1.4714 -1.469,1.4714 z"
|
||||
id="path13" />
|
||||
<path
|
||||
d="m 156.804,127.598 c -0.262,0 -0.524,-0.052 -0.787,-0.21 l -14.426,-9.249 c -0.682,-0.421 -0.892,-1.314 -0.42,-1.997 0.42,-0.684 1.312,-0.894 1.994,-0.421 l 14.426,9.249 c 0.682,0.421 0.892,1.314 0.42,1.997 -0.262,0.421 -0.734,0.631 -1.207,0.631 z"
|
||||
id="path14" />
|
||||
</g>
|
||||
<defs
|
||||
id="defs14">
|
||||
<clipPath
|
||||
id="clip0_45_75">
|
||||
<rect
|
||||
width="200"
|
||||
height="200"
|
||||
fill="currentColor"
|
||||
id="rect14" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.6 KiB |
BIN
src/interface/web/public/assets/icons/khoj_lantern_1200x1200.png
Normal file
BIN
src/interface/web/public/assets/icons/khoj_lantern_1200x1200.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
BIN
src/interface/web/public/assets/icons/khoj_lantern_512x512.png
Normal file
BIN
src/interface/web/public/assets/icons/khoj_lantern_512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -1,11 +1,18 @@
|
||||
{
|
||||
"name": "Khoj",
|
||||
"id": "https://app.khoj.dev",
|
||||
"name": "Khoj AI - Get Answers, Create Anything",
|
||||
"short_name": "Khoj",
|
||||
"display": "standalone",
|
||||
"start_url": "/",
|
||||
"description": "The open, personal AI for your digital brain. You can ask Khoj to draft a message, paint your imagination, find information on the internet and even answer questions from your documents.",
|
||||
"scope": "/",
|
||||
"description": "Khoj is your open, personal AI. Gets answers from the internet and your documents. Quickly draft messages, summarize any information, generate beautiful paintings, create personal agents and do deep research.",
|
||||
"categories": ["productivity", "utilities", "personalization", "education"],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"orientation": "natural",
|
||||
"launch_handler": {
|
||||
"client_mode": ["navigate-existing", "auto"]
|
||||
},
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/assets/icons/khoj_lantern_128x128.png",
|
||||
@@ -16,6 +23,24 @@
|
||||
"src": "/static/assets/icons/khoj_lantern_256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/assets/icons/khoj_lantern_512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/static/assets/icons/khoj_lantern_512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/static/assets/icons/khoj_lantern_1200x1200.png",
|
||||
"sizes": "1200x1200",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
}
|
||||
],
|
||||
"screenshots": [
|
||||
|
||||
@@ -55,6 +55,9 @@ const config = {
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ["var(--font-noto-sans)", "var(--font-noto-sans-arabic)"],
|
||||
},
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
|
||||
Reference in New Issue
Block a user