From 539ce9934317a6929b8dd4c33d86e4f73835da5d Mon Sep 17 00:00:00 2001 From: sabaimran Date: Wed, 8 Jan 2025 22:08:40 -0800 Subject: [PATCH 01/33] Add backend support for parsing and processing and storing mermaidjs diagrams - Replace default diagram output from excalidraw to mermaid - Retain typing of the excalidraw type for backwards compatibility in the chatlog --- src/khoj/database/models/__init__.py | 1 + src/khoj/processor/conversation/prompts.py | 119 ++++++++++++++++- src/khoj/processor/conversation/utils.py | 13 +- src/khoj/routers/api_chat.py | 18 +-- src/khoj/routers/helpers.py | 144 ++++++++++++++++++++- 5 files changed, 274 insertions(+), 21 deletions(-) diff --git a/src/khoj/database/models/__init__.py b/src/khoj/database/models/__init__.py index 68fae434..13e413b2 100644 --- a/src/khoj/database/models/__init__.py +++ b/src/khoj/database/models/__init__.py @@ -109,6 +109,7 @@ class ChatMessage(PydanticBaseModel): images: Optional[List[str]] = None queryFiles: Optional[List[Dict]] = None excalidrawDiagram: Optional[List[Dict]] = None + mermaidjsDiagram: str = None by: str turnId: Optional[str] = None intent: Optional[Intent] = None diff --git a/src/khoj/processor/conversation/prompts.py b/src/khoj/processor/conversation/prompts.py index 50e9184d..9501bc88 100644 --- a/src/khoj/processor/conversation/prompts.py +++ b/src/khoj/processor/conversation/prompts.py @@ -194,7 +194,7 @@ Limit your response to 3 sentences max. Be succinct, clear, and informative. ## Diagram Generation ## -- -improve_diagram_description_prompt = PromptTemplate.from_template( +improve_excalidraw_diagram_description_prompt = PromptTemplate.from_template( """ You are an architect working with a novice digital artist using a diagramming software. {personality_context} @@ -338,6 +338,123 @@ Diagram Description: {query} """.strip() ) +improve_mermaid_js_diagram_description_prompt = PromptTemplate.from_template( + """ +You are a senior architect working with an illustrator using a diagramming software. +{personality_context} + +Given a particular request, you need to translate it to to a detailed description that the illustrator can use to create a diagram. + +You can use the following diagram types in your instructions: +- Flowchart +- Sequence Diagram +- Gantt Chart (only for time-based queries after 0 AD) +- State Diagram +- Pie Chart + +Use these primitives to describe what sort of diagram the drawer should create in natural language, not special syntax. We must recreate the diagram every time, so include all relevant prior information in your description. + +- Describe the layout, components, and connections. +- Use simple, concise language. + +Today's Date: {current_date} +User's Location: {location} + +User's Notes: +{references} + +Online References: +{online_results} + +Conversation Log: +{chat_history} + +Query: {query} + +Enhanced Description: +""".strip() +) + +mermaid_js_diagram_generation_prompt = PromptTemplate.from_template( + """ +You are a designer with the ability to describe diagrams to compose in professional, fine detail. You dive into the details and make labels, connections, and shapes to represent complex systems. +{personality_context} + +----Goals---- +You need to create a declarative description of the diagram and relevant components, using the Mermaid.js syntax. + +You can choose from the following diagram types: +- Flowchart +- Sequence Diagram +- State Diagram +- Gantt Chart +- Pie Chart + +----Examples---- +--- +title: Node +--- + +flowchart LR + id["This is the start"] --> id2["This is the end"] + +sequenceDiagram + Alice->>John: Hello John, how are you? + John-->>Alice: Great! + Alice-)John: See you later! + +stateDiagram-v2 + [*] --> Still + Still --> [*] + + Still --> Moving + Moving --> Still + Moving --> Crash + Crash --> [*] + +gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + section Section + A task :a1, 2014-01-01, 30d + Another task :after a1, 20d + section Another + Task in Another :2014-01-12, 12d + another task :24d + +pie title Pets adopted by volunteers + "Dogs" : 10 + "Cats" : 30 + "Rats" : 60 + +flowchart TB + c1-->a2 + subgraph one + a1-->a2 + end + subgraph two + b1-->b2["this is b2"] + end + subgraph three + c1["this is c1"]-->c2["this is c2"] + end + one --> two + three --> two + two --> c2 + +----Process---- +Create your diagram with great composition and intuitiveness from the provided context and user prompt below. +- You may use subgraphs to group elements together. Each subgraph must have a title. +- **You must wrap ALL entity and node labels in double quotes**. For example, "Entity Name". +- Custom style are not permitted. Default styles only. +- JUST provide the diagram, no additional text or context. Say nothing else in your response except the diagram. +- Keep diagrams simple - maximum 15 nodes + +output: {query} + +""".strip() +) + failed_diagram_generation = PromptTemplate.from_template( """ You attempted to programmatically generate a diagram but failed due to a system issue. You are normally able to generate diagrams, but you encountered a system issue this time. diff --git a/src/khoj/processor/conversation/utils.py b/src/khoj/processor/conversation/utils.py index 883650ec..e8c78c75 100644 --- a/src/khoj/processor/conversation/utils.py +++ b/src/khoj/processor/conversation/utils.py @@ -266,7 +266,7 @@ def save_to_conversation_log( raw_query_files: List[FileAttachment] = [], generated_images: List[str] = [], raw_generated_files: List[FileAttachment] = [], - generated_excalidraw_diagram: str = None, + generated_mermaidjs_diagram: str = None, train_of_thought: List[Any] = [], tracer: Dict[str, Any] = {}, ): @@ -290,8 +290,8 @@ def save_to_conversation_log( "queryFiles": [file.model_dump(mode="json") for file in raw_generated_files], } - if generated_excalidraw_diagram: - khoj_message_metadata["excalidrawDiagram"] = generated_excalidraw_diagram + if generated_mermaidjs_diagram: + khoj_message_metadata["mermaidjsDiagram"] = generated_mermaidjs_diagram updated_conversation = message_to_log( user_message=q, @@ -441,7 +441,7 @@ def generate_chatml_messages_with_context( "query": chat.get("intent", {}).get("inferred-queries", [user_message])[0], } - if not is_none_or_empty(chat.get("excalidrawDiagram")) and role == "assistant": + if not is_none_or_empty(chat.get("mermaidjsDiagram")) and role == "assistant": generated_assets["diagram"] = { "query": chat.get("intent", {}).get("inferred-queries", [user_message])[0], } @@ -593,6 +593,11 @@ def clean_json(response: str): return response.strip().replace("\n", "").removeprefix("```json").removesuffix("```") +def clean_mermaidjs(response: str): + """Remove any markdown mermaidjs codeblock and newline formatting if present. Useful for non schema enforceable models""" + return response.strip().removeprefix("```mermaid").removesuffix("```") + + def clean_code_python(code: str): """Remove any markdown codeblock and newline formatting if present. Useful for non schema enforceable models""" return code.strip().removeprefix("```python").removesuffix("```") diff --git a/src/khoj/routers/api_chat.py b/src/khoj/routers/api_chat.py index 1f32ffda..64380e33 100644 --- a/src/khoj/routers/api_chat.py +++ b/src/khoj/routers/api_chat.py @@ -51,7 +51,7 @@ from khoj.routers.helpers import ( construct_automation_created_message, create_automation, gather_raw_query_files, - generate_excalidraw_diagram, + generate_mermaidjs_diagram, generate_summary_from_files, get_conversation_command, is_query_empty, @@ -781,7 +781,7 @@ async def chat( generated_images: List[str] = [] generated_files: List[FileAttachment] = [] - generated_excalidraw_diagram: str = None + generated_mermaidjs_diagram: str = None program_execution_context: List[str] = [] if conversation_commands == [ConversationCommand.Default]: @@ -1156,7 +1156,7 @@ async def chat( inferred_queries = [] diagram_description = "" - async for result in generate_excalidraw_diagram( + async for result in generate_mermaidjs_diagram( q=defiltered_query, conversation_history=meta_log, location_data=location, @@ -1172,12 +1172,12 @@ async def chat( if isinstance(result, dict) and ChatEvent.STATUS in result: yield result[ChatEvent.STATUS] else: - better_diagram_description_prompt, excalidraw_diagram_description = result - if better_diagram_description_prompt and excalidraw_diagram_description: + better_diagram_description_prompt, mermaidjs_diagram_description = result + if better_diagram_description_prompt and mermaidjs_diagram_description: inferred_queries.append(better_diagram_description_prompt) - diagram_description = excalidraw_diagram_description + diagram_description = mermaidjs_diagram_description - generated_excalidraw_diagram = diagram_description + generated_mermaidjs_diagram = diagram_description generated_asset_results["diagrams"] = { "query": better_diagram_description_prompt, @@ -1186,7 +1186,7 @@ async def chat( async for result in send_event( ChatEvent.GENERATED_ASSETS, { - "excalidrawDiagram": excalidraw_diagram_description, + "mermaidjsDiagram": mermaidjs_diagram_description, }, ): yield result @@ -1226,7 +1226,7 @@ async def chat( raw_query_files, generated_images, generated_files, - generated_excalidraw_diagram, + generated_mermaidjs_diagram, program_execution_context, generated_asset_results, tracer, diff --git a/src/khoj/routers/helpers.py b/src/khoj/routers/helpers.py index 4afc43f9..6a96843f 100644 --- a/src/khoj/routers/helpers.py +++ b/src/khoj/routers/helpers.py @@ -97,6 +97,7 @@ from khoj.processor.conversation.utils import ( ChatEvent, ThreadedGenerator, clean_json, + clean_mermaidjs, construct_chat_history, generate_chatml_messages_with_context, save_to_conversation_log, @@ -823,7 +824,7 @@ async def generate_better_diagram_description( elif online_results[result].get("webpages"): simplified_online_results[result] = online_results[result]["webpages"] - improve_diagram_description_prompt = prompts.improve_diagram_description_prompt.format( + improve_diagram_description_prompt = prompts.improve_excalidraw_diagram_description_prompt.format( query=q, chat_history=chat_history, location=location, @@ -887,6 +888,135 @@ async def generate_excalidraw_diagram_from_description( return response +async def generate_mermaidjs_diagram( + q: str, + conversation_history: Dict[str, Any], + location_data: LocationData, + note_references: List[Dict[str, Any]], + online_results: Optional[dict] = None, + query_images: List[str] = None, + user: KhojUser = None, + agent: Agent = None, + send_status_func: Optional[Callable] = None, + query_files: str = None, + tracer: dict = {}, +): + if send_status_func: + async for event in send_status_func("**Enhancing the Diagramming Prompt**"): + yield {ChatEvent.STATUS: event} + + better_diagram_description_prompt = await generate_better_mermaidjs_diagram_description( + q=q, + conversation_history=conversation_history, + location_data=location_data, + note_references=note_references, + online_results=online_results, + query_images=query_images, + user=user, + agent=agent, + query_files=query_files, + tracer=tracer, + ) + + if send_status_func: + async for event in send_status_func(f"**Diagram to Create:**:\n{better_diagram_description_prompt}"): + yield {ChatEvent.STATUS: event} + + mermaidjs_diagram_description = await generate_mermaidjs_diagram_from_description( + q=better_diagram_description_prompt, + user=user, + agent=agent, + tracer=tracer, + ) + + inferred_queries = f"Instruction: {better_diagram_description_prompt}" + + yield inferred_queries, mermaidjs_diagram_description + + +async def generate_better_mermaidjs_diagram_description( + q: str, + conversation_history: Dict[str, Any], + location_data: LocationData, + note_references: List[Dict[str, Any]], + online_results: Optional[dict] = None, + query_images: List[str] = None, + user: KhojUser = None, + agent: Agent = None, + query_files: str = None, + tracer: dict = {}, +) -> str: + """ + Generate a diagram description from the given query and context + """ + + today_date = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d, %A") + personality_context = ( + prompts.personality_context.format(personality=agent.personality) if agent and agent.personality else "" + ) + + location = f"{location_data}" if location_data else "Unknown" + + user_references = "\n\n".join([f"# {item['compiled']}" for item in note_references]) + + chat_history = construct_chat_history(conversation_history) + + simplified_online_results = {} + + if online_results: + for result in online_results: + if online_results[result].get("answerBox"): + simplified_online_results[result] = online_results[result]["answerBox"] + elif online_results[result].get("webpages"): + simplified_online_results[result] = online_results[result]["webpages"] + + improve_diagram_description_prompt = prompts.improve_mermaid_js_diagram_description_prompt.format( + query=q, + chat_history=chat_history, + location=location, + current_date=today_date, + references=user_references, + online_results=simplified_online_results, + personality_context=personality_context, + ) + + with timer("Chat actor: Generate better Mermaid.js diagram description", logger): + response = await send_message_to_model_wrapper( + improve_diagram_description_prompt, + query_images=query_images, + user=user, + query_files=query_files, + tracer=tracer, + ) + response = response.strip() + if response.startswith(('"', "'")) and response.endswith(('"', "'")): + response = response[1:-1] + + return response + + +async def generate_mermaidjs_diagram_from_description( + q: str, + user: KhojUser = None, + agent: Agent = None, + tracer: dict = {}, +) -> Dict[str, Any]: + personality_context = ( + prompts.personality_context.format(personality=agent.personality) if agent and agent.personality else "" + ) + + mermaidjs_diagram_generation = prompts.mermaid_js_diagram_generation_prompt.format( + personality_context=personality_context, + query=q, + ) + + with timer("Chat actor: Generate Mermaid.js diagram", logger): + raw_response = await send_message_to_model_wrapper(query=mermaidjs_diagram_generation, user=user, tracer=tracer) + return clean_mermaidjs(raw_response.strip()) + + return response + + async def generate_better_image_prompt( q: str, conversation_history: str, @@ -1222,7 +1352,7 @@ def generate_chat_response( raw_query_files: List[FileAttachment] = None, generated_images: List[str] = None, raw_generated_files: List[FileAttachment] = [], - generated_excalidraw_diagram: str = None, + generated_mermaidjs_diagram: str = None, program_execution_context: List[str] = [], generated_asset_results: Dict[str, Dict] = {}, tracer: dict = {}, @@ -1250,7 +1380,7 @@ def generate_chat_response( raw_query_files=raw_query_files, generated_images=generated_images, raw_generated_files=raw_generated_files, - generated_excalidraw_diagram=generated_excalidraw_diagram, + generated_mermaidjs_diagram=generated_mermaidjs_diagram, tracer=tracer, ) @@ -1965,7 +2095,7 @@ class MessageProcessor: self.raw_response = "" self.generated_images = [] self.generated_files = [] - self.generated_excalidraw_diagram = [] + self.generated_mermaidjs_diagram = [] def convert_message_chunk_to_json(self, raw_chunk: str) -> Dict[str, Any]: if raw_chunk.startswith("{") and raw_chunk.endswith("}"): @@ -2012,8 +2142,8 @@ class MessageProcessor: self.generated_images = chunk_data[key] elif key == "files": self.generated_files = chunk_data[key] - elif key == "excalidrawDiagram": - self.generated_excalidraw_diagram = chunk_data[key] + elif key == "mermaidjsDiagram": + self.generated_mermaidjs_diagram = chunk_data[key] def handle_json_response(self, json_data: Dict[str, str]) -> str | Dict[str, str]: if "image" in json_data or "details" in json_data: @@ -2050,7 +2180,7 @@ async def read_chat_stream(response_iterator: AsyncGenerator[str, None]) -> Dict "usage": processor.usage, "images": processor.generated_images, "files": processor.generated_files, - "excalidrawDiagram": processor.generated_excalidraw_diagram, + "mermaidjsDiagram": processor.generated_mermaidjs_diagram, } From 6b0a49b12d9009f5321ecafa4c24cbc1a55ebced Mon Sep 17 00:00:00 2001 From: sabaimran Date: Wed, 8 Jan 2025 22:09:35 -0800 Subject: [PATCH 02/33] Add the mermaid package and apply front-end parsing - Add the mermaid package and apply front-end parsing for interpreting the diagrams. Retain processing of the excalidraw type for backwards compatibility --- src/interface/web/app/common/chatFunctions.ts | 6 +- .../components/chatHistory/chatHistory.tsx | 2 +- .../components/chatMessage/chatMessage.tsx | 11 + .../web/app/components/mermaid/mermaid.tsx | 68 ++ src/interface/web/package.json | 1 + src/interface/web/yarn.lock | 891 +++++++++++++++++- 6 files changed, 972 insertions(+), 7 deletions(-) create mode 100644 src/interface/web/app/components/mermaid/mermaid.tsx diff --git a/src/interface/web/app/common/chatFunctions.ts b/src/interface/web/app/common/chatFunctions.ts index c64e81ba..be64acf1 100644 --- a/src/interface/web/app/common/chatFunctions.ts +++ b/src/interface/web/app/common/chatFunctions.ts @@ -19,7 +19,7 @@ export interface MessageMetadata { export interface GeneratedAssetsData { images: string[]; - excalidrawDiagram: string; + mermaidjsDiagram: string; files: AttachedFileText[]; } @@ -114,8 +114,8 @@ export function processMessageChunk( currentMessage.generatedImages = generatedAssets.images; } - if (generatedAssets.excalidrawDiagram) { - currentMessage.generatedExcalidrawDiagram = generatedAssets.excalidrawDiagram; + if (generatedAssets.mermaidjsDiagram) { + currentMessage.generatedMermaidjsDiagram = generatedAssets.mermaidjsDiagram; } if (generatedAssets.files) { diff --git a/src/interface/web/app/components/chatHistory/chatHistory.tsx b/src/interface/web/app/components/chatHistory/chatHistory.tsx index 5a750e8b..829211be 100644 --- a/src/interface/web/app/components/chatHistory/chatHistory.tsx +++ b/src/interface/web/app/components/chatHistory/chatHistory.tsx @@ -418,7 +418,7 @@ export default function ChatHistory(props: ChatHistoryProps) { conversationId: props.conversationId, images: message.generatedImages, queryFiles: message.generatedFiles, - excalidrawDiagram: message.generatedExcalidrawDiagram, + mermaidjsDiagram: message.generatedMermaidjsDiagram, turnId: messageTurnId, }} conversationId={props.conversationId} diff --git a/src/interface/web/app/components/chatMessage/chatMessage.tsx b/src/interface/web/app/components/chatMessage/chatMessage.tsx index 89c3038a..c3227f59 100644 --- a/src/interface/web/app/components/chatMessage/chatMessage.tsx +++ b/src/interface/web/app/components/chatMessage/chatMessage.tsx @@ -53,6 +53,7 @@ import { DialogTitle } from "@radix-ui/react-dialog"; import { convertBytesToText } from "@/app/common/utils"; import { ScrollArea } from "@/components/ui/scroll-area"; import { getIconFromFilename } from "@/app/common/iconUtils"; +import Mermaid from "../mermaid/mermaid"; const md = new markdownIt({ html: true, @@ -164,6 +165,7 @@ export interface SingleChatMessage { turnId?: string; queryFiles?: AttachedFileText[]; excalidrawDiagram?: string; + mermaidjsDiagram?: string; } export interface StreamMessage { @@ -182,9 +184,11 @@ export interface StreamMessage { turnId?: string; queryFiles?: AttachedFileText[]; excalidrawDiagram?: string; + mermaidjsDiagram?: string; generatedFiles?: AttachedFileText[]; generatedImages?: string[]; generatedExcalidrawDiagram?: string; + generatedMermaidjsDiagram?: string; } export interface ChatHistoryData { @@ -271,6 +275,7 @@ interface ChatMessageProps { turnId?: string; generatedImage?: string; excalidrawDiagram?: string; + mermaidjsDiagram?: string; generatedFiles?: AttachedFileText[]; } @@ -358,6 +363,7 @@ const ChatMessage = forwardRef((props, ref) => const [isPlaying, setIsPlaying] = useState(false); const [interrupted, setInterrupted] = useState(false); const [excalidrawData, setExcalidrawData] = useState(""); + const [mermaidjsData, setMermaidjsData] = useState(""); const interruptedRef = useRef(false); const messageRef = useRef(null); @@ -401,6 +407,10 @@ const ChatMessage = forwardRef((props, ref) => setExcalidrawData(props.chatMessage.excalidrawDiagram); } + if (props.chatMessage.mermaidjsDiagram) { + setMermaidjsData(props.chatMessage.mermaidjsDiagram); + } + // Replace LaTeX delimiters with placeholders message = message .replace(/\\\(/g, "LEFTPAREN") @@ -718,6 +728,7 @@ const ChatMessage = forwardRef((props, ref) => dangerouslySetInnerHTML={{ __html: markdownRendered }} /> {excalidrawData && } + {mermaidjsData && }
= ({ chart }) => { + const [mermaidError, setMermaidError] = useState(null); + const [mermaidId] = useState(`mermaid-chart-${Math.random().toString(12).substring(7)}`); + const elementRef = useRef(null); + + useEffect(() => { + mermaid.initialize({ + startOnLoad: false, + }); + + mermaid.parseError = (error) => { + console.error("Mermaid errors:", error); + // Extract error message from error object + const errorMessage = JSON.stringify(error); + setMermaidError(errorMessage); + }; + + mermaid.contentLoaded(); + }, []); + + useEffect(() => { + console.log("Rendering mermaid chart:", chart); + if (elementRef.current) { + elementRef.current.removeAttribute("data-processed"); + + mermaid + .run({ + nodes: [elementRef.current], + }) + .then(() => { + setMermaidError(null); + }) + .catch((error) => { + console.error("Mermaid error:", error); + // Extract error message from error object + const errorMessage = error?.str || error?.message || JSON.stringify(error); + console.log("Mermaid error message:", errorMessage); + }); + } + }, [chart]); + + return ( +
+
+ {chart} +
+
+ ); +}; + +export default Mermaid; diff --git a/src/interface/web/package.json b/src/interface/web/package.json index 3fa63f26..9439b401 100644 --- a/src/interface/web/package.json +++ b/src/interface/web/package.json @@ -58,6 +58,7 @@ "lucide-react": "^0.468.0", "markdown-it": "^14.1.0", "markdown-it-highlightjs": "^4.1.0", + "mermaid": "^11.4.1", "next": "14.2.15", "nodemon": "^3.1.3", "postcss": "^8.4.38", diff --git a/src/interface/web/yarn.lock b/src/interface/web/yarn.lock index 200bdab8..14aec059 100644 --- a/src/interface/web/yarn.lock +++ b/src/interface/web/yarn.lock @@ -15,11 +15,24 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" +"@antfu/install-pkg@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-0.4.1.tgz#d1d7f3be96ecdb41581629cafe8626d1748c0cf1" + integrity sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw== + dependencies: + package-manager-detector "^0.2.0" + tinyexec "^0.3.0" + "@antfu/ni@^0.21.4": version "0.21.12" resolved "https://registry.yarnpkg.com/@antfu/ni/-/ni-0.21.12.tgz#54d33cf0e6d35cb2ec12ab3d5092e4904540b7c0" integrity sha512-2aDL3WUv8hMJb2L3r/PIQWsTLyq7RQr3v9xD16fiz6O8ys1xEyLhhTOv8gxtZvJiTzjTF5pHoArvRdesGL1DMQ== +"@antfu/utils@^0.7.10": + version "0.7.10" + resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.7.10.tgz#ae829f170158e297a9b6a28f161a8e487d00814d" + integrity sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww== + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" @@ -229,6 +242,43 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@braintree/sanitize-url@^7.0.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz#15e19737d946559289b915e5dad3b4c28407735e" + integrity sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw== + +"@chevrotain/cst-dts-gen@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz#5e0863cc57dc45e204ccfee6303225d15d9d4783" + integrity sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ== + dependencies: + "@chevrotain/gast" "11.0.3" + "@chevrotain/types" "11.0.3" + lodash-es "4.17.21" + +"@chevrotain/gast@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/gast/-/gast-11.0.3.tgz#e84d8880323fe8cbe792ef69ce3ffd43a936e818" + integrity sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q== + dependencies: + "@chevrotain/types" "11.0.3" + lodash-es "4.17.21" + +"@chevrotain/regexp-to-ast@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz#11429a81c74a8e6a829271ce02fc66166d56dcdb" + integrity sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA== + +"@chevrotain/types@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/types/-/types-11.0.3.tgz#f8a03914f7b937f594f56eb89312b3b8f1c91848" + integrity sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ== + +"@chevrotain/utils@11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@chevrotain/utils/-/utils-11.0.3.tgz#e39999307b102cff3645ec4f5b3665f5297a2224" + integrity sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ== + "@eslint-community/eslint-utils@^4.2.0": version "4.4.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" @@ -317,6 +367,25 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@iconify/types@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" + integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== + +"@iconify/utils@^2.1.32": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-2.2.1.tgz#635b9bd8fd3e5e53742471bc0b5291f1570dda41" + integrity sha512-0/7J7hk4PqXmxo5PDBDxmnecw5PxklZJfNjIVG9FM0mEfVrvfudS22rYWsqVk6gR3UJ/mSYS90X4R3znXnqfNA== + dependencies: + "@antfu/install-pkg" "^0.4.1" + "@antfu/utils" "^0.7.10" + "@iconify/types" "^2.0.0" + debug "^4.4.0" + globals "^15.13.0" + kolorist "^1.8.0" + local-pkg "^0.5.1" + mlly "^1.7.3" + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -361,6 +430,13 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@mermaid-js/parser@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@mermaid-js/parser/-/parser-0.3.0.tgz#7a28714599f692f93df130b299fa1aadc9f9c8ab" + integrity sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA== + dependencies: + langium "3.0.0" + "@next/env@14.2.15": version "14.2.15" resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.15.tgz#06d984e37e670d93ddd6790af1844aeb935f332f" @@ -1114,6 +1190,216 @@ mkdirp "^2.1.6" path-browserify "^1.0.1" +"@types/d3-array@*": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + +"@types/d3-axis@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795" + integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c" + integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d" + integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-contour@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231" + integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1" + integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw== + +"@types/d3-dispatch@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7" + integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ== + +"@types/d3-drag@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02" + integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17" + integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g== + +"@types/d3-ease@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-fetch@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980" + integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.10.tgz#6dc8fc6e1f35704f3b057090beeeb7ac674bff1a" + integrity sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw== + +"@types/d3-format@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90" + integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g== + +"@types/d3-geo@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b" + integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg== + +"@types/d3-interpolate@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a" + integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ== + +"@types/d3-polygon@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c" + integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA== + +"@types/d3-quadtree@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f" + integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg== + +"@types/d3-random@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb" + integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ== + +"@types/d3-scale-chromatic@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#dc6d4f9a98376f18ea50bad6c39537f1b5463c39" + integrity sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ== + +"@types/d3-scale@*": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.11.tgz#bd7a45fc0a8c3167a631675e61bc2ca2b058d4a3" + integrity sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w== + +"@types/d3-shape@*": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.7.tgz#2b7b423dc2dfe69c8c93596e673e37443348c555" + integrity sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2" + integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg== + +"@types/d3-time@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== + +"@types/d3-timer@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== + +"@types/d3-transition@*": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.9.tgz#1136bc57e9ddb3c390dccc9b5ff3b7d2b8d94706" + integrity sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b" + integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.4.3": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2" + integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww== + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-fetch" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" + "@types/dompurify@^3.0.5": version "3.2.0" resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.2.0.tgz#56610bf3e4250df57744d61fbd95422e07dfb840" @@ -1121,6 +1407,11 @@ dependencies: dompurify "*" +"@types/geojson@*": + version "7946.0.15" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.15.tgz#f9d55fd5a0aa2de9dc80b1b04e437538b7298868" + integrity sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA== + "@types/intl-tel-input@^18.1.4": version "18.1.4" resolved "https://registry.yarnpkg.com/@types/intl-tel-input/-/intl-tel-input-18.1.4.tgz#0eb5211a7490f8a8d7aa940ee594a85138d514c9" @@ -1254,7 +1545,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.9.0: +acorn@^8.14.0, acorn@^8.9.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -1602,6 +1893,25 @@ chalk@^5.0.0, chalk@~5.3.0: resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== +chevrotain-allstar@~0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz#b7412755f5d83cc139ab65810cdb00d8db40e6ca" + integrity sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw== + dependencies: + lodash-es "^4.17.21" + +chevrotain@~11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/chevrotain/-/chevrotain-11.0.3.tgz#88ffc1fb4b5739c715807eaeedbbf200e202fc1b" + integrity sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw== + dependencies: + "@chevrotain/cst-dts-gen" "11.0.3" + "@chevrotain/gast" "11.0.3" + "@chevrotain/regexp-to-ast" "11.0.3" + "@chevrotain/types" "11.0.3" + "@chevrotain/utils" "11.0.3" + lodash-es "4.17.21" + chokidar@^3.5.2, chokidar@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -1703,6 +2013,11 @@ colorette@^2.0.20: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== +commander@7: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" @@ -1728,11 +2043,30 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cose-base@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-1.0.3.tgz#650334b41b869578a543358b80cda7e0abe0a60a" + integrity sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg== + dependencies: + layout-base "^1.0.0" + +cose-base@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-2.2.0.tgz#1c395c35b6e10bb83f9769ca8b817d614add5c01" + integrity sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g== + dependencies: + layout-base "^2.0.0" + cosmiconfig@^8.1.3: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" @@ -1767,6 +2101,304 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== +cytoscape-cose-bilkent@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz#762fa121df9930ffeb51a495d87917c570ac209b" + integrity sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ== + dependencies: + cose-base "^1.0.0" + +cytoscape-fcose@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz#e4d6f6490df4fab58ae9cea9e5c3ab8d7472f471" + integrity sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ== + dependencies: + cose-base "^2.2.0" + +cytoscape@^3.29.2: + version "3.30.4" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.30.4.tgz#3404da0a159c00a1a3df2c85b2b43fdc66a0e28e" + integrity sha512-OxtlZwQl1WbwMmLiyPSEBuzeTIQnwZhJYYWFzZ2PhEHVFwpeaqNIkUzSiso00D98qk60l8Gwon2RP304d3BJ1A== + +"d3-array@1 - 2": + version "2.12.1" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" + integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== + dependencies: + internmap "^1.0.0" + +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-contour@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" + integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== + dependencies: + d3-array "^3.2.0" + +d3-delaunay@6: + version "6.0.4" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d" + integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-sankey@^0.12.3: + version "0.12.3" + resolved "https://registry.yarnpkg.com/d3-sankey/-/d3-sankey-0.12.3.tgz#b3c268627bd72e5d80336e8de6acbfec9d15d01d" + integrity sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ== + dependencies: + d3-array "1 - 2" + d3-shape "^1.2.0" + +d3-scale-chromatic@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +d3-shape@^1.2.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.9.0: + version "7.9.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d" + integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "4" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + +dagre-d3-es@7.0.11: + version "7.0.11" + resolved "https://registry.yarnpkg.com/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz#2237e726c0577bfe67d1a7cfd2265b9ab2c15c40" + integrity sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw== + dependencies: + d3 "^7.9.0" + lodash-es "^4.17.21" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -1804,7 +2436,12 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" -debug@4, debug@^4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7, debug@~4.4.0: +dayjs@^1.11.10: + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + +debug@4, debug@^4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7, debug@^4.4.0, debug@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== @@ -1848,6 +2485,13 @@ define-properties@^1.1.3, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delaunator@5: + version "5.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== + dependencies: + robust-predicates "^3.0.2" + detect-node-es@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" @@ -1889,7 +2533,7 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dompurify@*, dompurify@^3.1.6: +dompurify@*, dompurify@^3.1.6, dompurify@^3.2.1: version "3.2.3" resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.3.tgz#05dd2175225324daabfca6603055a09b2382a4cd" integrity sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA== @@ -2635,6 +3279,11 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^15.13.0: + version "15.14.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.14.0.tgz#b8fd3a8941ff3b4d38f3319d433b61bbb482e73f" + integrity sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig== + globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" @@ -2670,6 +3319,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +hachure-fill@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/hachure-fill/-/hachure-fill-0.5.2.tgz#d19bc4cc8750a5962b47fb1300557a85fcf934cc" + integrity sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg== + has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -2746,6 +3400,13 @@ husky@^9.0.11: resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== +iconv-lite@0.6: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -2801,6 +3462,16 @@ internal-slot@^1.0.7, internal-slot@^1.1.0: hasown "^2.0.2" side-channel "^1.1.0" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + +internmap@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" + integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== + intl-tel-input@^23.8.1: version "23.9.3" resolved "https://registry.yarnpkg.com/intl-tel-input/-/intl-tel-input-23.9.3.tgz#3870c78c16655bdc13e18cae557efcaa43dce719" @@ -3157,6 +3828,13 @@ katex@^0.16.10: dependencies: commander "^8.3.0" +katex@^0.16.9: + version "0.16.19" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.19.tgz#698e026188876f9c8c93d3ecb27b212aaa056d0a" + integrity sha512-3IA6DYVhxhBabjSLTNO9S4+OliA3Qvb8pBQXMfC4WxXJgLwZgnfDl0BmB4z6nBMdznBsZ+CGM8DrGZ5hcguDZg== + dependencies: + commander "^8.3.0" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -3164,11 +3842,32 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" +khroma@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" + integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +langium@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/langium/-/langium-3.0.0.tgz#4938294eb57c59066ef955070ac4d0c917b26026" + integrity sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg== + dependencies: + chevrotain "~11.0.3" + chevrotain-allstar "~0.3.0" + vscode-languageserver "~9.0.1" + vscode-languageserver-textdocument "~1.0.11" + vscode-uri "~3.0.8" + language-subtag-registry@^0.3.20: version "0.3.23" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" @@ -3181,6 +3880,16 @@ language-tags@^1.0.9: dependencies: language-subtag-registry "^0.3.20" +layout-base@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-1.0.2.tgz#1291e296883c322a9dd4c5dd82063721b53e26e2" + integrity sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg== + +layout-base@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285" + integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -3239,6 +3948,14 @@ listr2@~8.2.5: rfdc "^1.4.1" wrap-ansi "^9.0.0" +local-pkg@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.1.tgz#69658638d2a95287534d4c2fff757980100dbb6d" + integrity sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ== + dependencies: + mlly "^1.7.3" + pkg-types "^1.2.1" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -3246,6 +3963,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@4.17.21, lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -3318,6 +4040,11 @@ markdown-it@^14.1.0: punycode.js "^2.3.1" uc.micro "^2.1.0" +marked@^13.0.2: + version "13.0.3" + resolved "https://registry.yarnpkg.com/marked/-/marked-13.0.3.tgz#5c5b4a5d0198060c7c9bc6ef9420a7fed30f822d" + integrity sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA== + math-intrinsics@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.0.0.tgz#4e04bf87c85aa51e90d078dac2252b4eb5260817" @@ -3338,6 +4065,32 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +mermaid@^11.4.1: + version "11.4.1" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-11.4.1.tgz#577fad5c31a01a06d9f793e298d411f1379eecc8" + integrity sha512-Mb01JT/x6CKDWaxigwfZYuYmDZ6xtrNwNlidKZwkSrDaY9n90tdrJTV5Umk+wP1fZscGptmKFXHsXMDEVZ+Q6A== + dependencies: + "@braintree/sanitize-url" "^7.0.1" + "@iconify/utils" "^2.1.32" + "@mermaid-js/parser" "^0.3.0" + "@types/d3" "^7.4.3" + cytoscape "^3.29.2" + cytoscape-cose-bilkent "^4.1.0" + cytoscape-fcose "^2.2.0" + d3 "^7.9.0" + d3-sankey "^0.12.3" + dagre-d3-es "7.0.11" + dayjs "^1.11.10" + dompurify "^3.2.1" + katex "^0.16.9" + khroma "^2.1.0" + lodash-es "^4.17.21" + marked "^13.0.2" + roughjs "^4.6.6" + stylis "^4.3.1" + ts-dedent "^2.2.0" + uuid "^9.0.1" + micromatch@^4.0.4, micromatch@^4.0.8, micromatch@~4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" @@ -3404,6 +4157,16 @@ mkdirp@^2.1.6: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== +mlly@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.3.tgz#d86c0fcd8ad8e16395eb764a5f4b831590cee48c" + integrity sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A== + dependencies: + acorn "^8.14.0" + pathe "^1.1.2" + pkg-types "^1.2.1" + ufo "^1.5.4" + ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" @@ -3644,6 +4407,11 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== +package-manager-detector@^0.2.0: + version "0.2.8" + resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-0.2.8.tgz#f5ace2dbd37666af54e5acec11bc37c8450f72d0" + integrity sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -3666,6 +4434,11 @@ path-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== +path-data-parser@0.1.0, path-data-parser@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/path-data-parser/-/path-data-parser-0.1.0.tgz#8f5ba5cc70fc7becb3dcefaea08e2659aba60b8c" + integrity sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -3704,6 +4477,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -3729,6 +4507,28 @@ pirates@^4.0.1: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== +pkg-types@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.0.tgz#53d915eb99485798c554ad8eb2dc2af7c03006eb" + integrity sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg== + dependencies: + confbox "^0.1.8" + mlly "^1.7.3" + pathe "^1.1.2" + +points-on-curve@0.2.0, points-on-curve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/points-on-curve/-/points-on-curve-0.2.0.tgz#7dbb98c43791859434284761330fa893cb81b4d1" + integrity sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A== + +points-on-path@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/points-on-path/-/points-on-path-0.2.1.tgz#553202b5424c53bed37135b318858eacff85dd52" + integrity sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g== + dependencies: + path-data-parser "0.1.0" + points-on-curve "0.2.0" + possible-typed-array-names@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" @@ -4021,6 +4821,21 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +robust-predicates@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + +roughjs@^4.6.6: + version "4.6.6" + resolved "https://registry.yarnpkg.com/roughjs/-/roughjs-4.6.6.tgz#1059f49a5e0c80dee541a005b20cc322b222158b" + integrity sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ== + dependencies: + hachure-fill "^0.5.2" + path-data-parser "^0.1.0" + points-on-curve "^0.2.0" + points-on-path "^0.2.1" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -4028,6 +4843,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + safe-array-concat@^1.1.2, safe-array-concat@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" @@ -4053,6 +4873,11 @@ safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: es-errors "^1.3.0" is-regex "^1.2.1" +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + scheduler@^0.23.2: version "0.23.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" @@ -4383,6 +5208,11 @@ styled-jsx@5.1.1: dependencies: client-only "0.0.1" +stylis@^4.3.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.4.tgz#ca5c6c4a35c4784e4e93a2a24dc4e9fa075250a4" + integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now== + sucrase@^3.35.0: version "3.35.0" resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" @@ -4498,6 +5328,11 @@ tiny-invariant@^1.3.3: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== +tinyexec@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -4515,6 +5350,11 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" @@ -4619,6 +5459,11 @@ uc.micro@^2.0.0, uc.micro@^2.1.0: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== +ufo@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754" + integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== + unbox-primitive@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" @@ -4684,6 +5529,11 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + vaul@^0.9.1: version "0.9.9" resolved "https://registry.yarnpkg.com/vaul/-/vaul-0.9.9.tgz#ff075c3cba6193d4859bb6f1b09efcce049cf812" @@ -4691,6 +5541,41 @@ vaul@^0.9.1: dependencies: "@radix-ui/react-dialog" "^1.1.1" +vscode-jsonrpc@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" + integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA== + +vscode-languageserver-protocol@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea" + integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg== + dependencies: + vscode-jsonrpc "8.2.0" + vscode-languageserver-types "3.17.5" + +vscode-languageserver-textdocument@~1.0.11: + version "1.0.12" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" + integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA== + +vscode-languageserver-types@3.17.5: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== + +vscode-languageserver@~9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz#500aef82097eb94df90d008678b0b6b5f474015b" + integrity sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g== + dependencies: + vscode-languageserver-protocol "3.17.5" + +vscode-uri@~3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" + integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== + wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" From 11fcf2f299d017b2af4c84905d90e44d23e3ea4c Mon Sep 17 00:00:00 2001 From: sabaimran Date: Wed, 8 Jan 2025 22:10:59 -0800 Subject: [PATCH 03/33] Remove dangling response type --- src/khoj/routers/helpers.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/khoj/routers/helpers.py b/src/khoj/routers/helpers.py index 6a96843f..4455f0df 100644 --- a/src/khoj/routers/helpers.py +++ b/src/khoj/routers/helpers.py @@ -1014,8 +1014,6 @@ async def generate_mermaidjs_diagram_from_description( raw_response = await send_message_to_model_wrapper(query=mermaidjs_diagram_generation, user=user, tracer=tracer) return clean_mermaidjs(raw_response.strip()) - return response - async def generate_better_image_prompt( q: str, From 889f34c7bf98b2732175b34a7bdc72818c219736 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Wed, 8 Jan 2025 23:22:16 -0800 Subject: [PATCH 04/33] Adjust typing and error handling for incorrect diagrams --- .../web/app/components/mermaid/mermaid.tsx | 60 ++++++++++++------- src/khoj/processor/conversation/prompts.py | 22 +++---- src/khoj/routers/helpers.py | 2 +- 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/interface/web/app/components/mermaid/mermaid.tsx b/src/interface/web/app/components/mermaid/mermaid.tsx index f382d095..193d9d81 100644 --- a/src/interface/web/app/components/mermaid/mermaid.tsx +++ b/src/interface/web/app/components/mermaid/mermaid.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState, useRef } from "react"; import mermaid from "mermaid"; +import { Info } from "@phosphor-icons/react"; interface MermaidProps { chart: string; @@ -18,8 +19,23 @@ const Mermaid: React.FC = ({ chart }) => { mermaid.parseError = (error) => { console.error("Mermaid errors:", error); // Extract error message from error object - const errorMessage = JSON.stringify(error); - setMermaidError(errorMessage); + // Parse error message safely + let errorMessage; + try { + errorMessage = typeof error === "string" ? JSON.parse(error) : error; + } catch (e) { + errorMessage = error?.toString() || "Unknown error"; + } + + console.log("Mermaid error message:", errorMessage); + + if (errorMessage.str !== "element is null") { + setMermaidError( + "Something went wrong while rendering the diagram. Please try again later or downvote the message if the issue persists.", + ); + } else { + setMermaidError(null); + } }; mermaid.contentLoaded(); @@ -37,30 +53,32 @@ const Mermaid: React.FC = ({ chart }) => { .then(() => { setMermaidError(null); }) - .catch((error) => { - console.error("Mermaid error:", error); - // Extract error message from error object - const errorMessage = error?.str || error?.message || JSON.stringify(error); - console.log("Mermaid error message:", errorMessage); - }); + .catch((error) => {}); } }, [chart]); return (
-
- {chart} -
+ {mermaidError ? ( +
+ + Error rendering diagram: {mermaidError} +
+ ) : ( +
+ {chart} +
+ )}
); }; diff --git a/src/khoj/processor/conversation/prompts.py b/src/khoj/processor/conversation/prompts.py index 9501bc88..ee509cf9 100644 --- a/src/khoj/processor/conversation/prompts.py +++ b/src/khoj/processor/conversation/prompts.py @@ -428,27 +428,27 @@ pie title Pets adopted by volunteers "Rats" : 60 flowchart TB - c1-->a2 - subgraph one - a1-->a2 + subgraph "Group 1" + a1["Start Node"] --> a2["End Node"] end - subgraph two - b1-->b2["this is b2"] + subgraph "Group 2" + b1["Process 1"] --> b2["Process 2"] end - subgraph three - c1["this is c1"]-->c2["this is c2"] + subgraph "Group 3" + c1["Input"] --> c2["Output"] end - one --> two - three --> two - two --> c2 + a["Group 1"] --> b["Group 2"] + c["Group 3"] --> d["Group 2"] ----Process---- Create your diagram with great composition and intuitiveness from the provided context and user prompt below. - You may use subgraphs to group elements together. Each subgraph must have a title. -- **You must wrap ALL entity and node labels in double quotes**. For example, "Entity Name". +- **You must wrap ALL entity and node labels in double quotes**, example: "My Node Label" +- **All nodes MUST use the id["label"] format**. For example: node1["My Node Label"] - Custom style are not permitted. Default styles only. - JUST provide the diagram, no additional text or context. Say nothing else in your response except the diagram. - Keep diagrams simple - maximum 15 nodes +- Every node inside a subgraph MUST use square bracket notation: id["label"] output: {query} diff --git a/src/khoj/routers/helpers.py b/src/khoj/routers/helpers.py index 4455f0df..d8bc932d 100644 --- a/src/khoj/routers/helpers.py +++ b/src/khoj/routers/helpers.py @@ -1000,7 +1000,7 @@ async def generate_mermaidjs_diagram_from_description( user: KhojUser = None, agent: Agent = None, tracer: dict = {}, -) -> Dict[str, Any]: +) -> str: personality_context = ( prompts.personality_context.format(personality=agent.personality) if agent and agent.personality else "" ) From ec02757fd10f03beec9bc27716def3262c93b6c0 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Wed, 8 Jan 2025 23:53:58 -0800 Subject: [PATCH 05/33] Add an export feature along with the mermaid diagram. Add sidebar to loading page. --- .../web/app/components/loading/loading.tsx | 47 +++++++++--- .../web/app/components/mermaid/mermaid.tsx | 74 ++++++++++++++++++- 2 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/interface/web/app/components/loading/loading.tsx b/src/interface/web/app/components/loading/loading.tsx index 30761f9a..1e3ebf49 100644 --- a/src/interface/web/app/components/loading/loading.tsx +++ b/src/interface/web/app/components/loading/loading.tsx @@ -1,4 +1,9 @@ +import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"; import { CircleNotch } from "@phosphor-icons/react"; +import { AppSidebar } from "../appSidebar/appSidebar"; +import { Separator } from "@/components/ui/separator"; +import { useIsMobileWidth } from "@/app/common/utils"; +import { KhojLogoType } from "../logo/khojLogo"; interface LoadingProps { className?: string; @@ -7,21 +12,39 @@ interface LoadingProps { } export default function Loading(props: LoadingProps) { + const isMobileWidth = useIsMobileWidth(); + return ( // NOTE: We can display usage tips here for casual learning moments. -
-
- {props.message || "Loading"}{" "} - - - + + + +
+ + + {isMobileWidth ? ( + + + + ) : ( +

Ask Anything

+ )} +
+
+
+
+ {props.message || "Loading"}{" "} + + + +
-
+ ); } diff --git a/src/interface/web/app/components/mermaid/mermaid.tsx b/src/interface/web/app/components/mermaid/mermaid.tsx index 193d9d81..14c71d99 100644 --- a/src/interface/web/app/components/mermaid/mermaid.tsx +++ b/src/interface/web/app/components/mermaid/mermaid.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState, useRef } from "react"; import mermaid from "mermaid"; -import { Info } from "@phosphor-icons/react"; +import { Download, Info } from "@phosphor-icons/react"; +import { Button } from "@/components/ui/button"; interface MermaidProps { chart: string; @@ -41,8 +42,71 @@ const Mermaid: React.FC = ({ chart }) => { mermaid.contentLoaded(); }, []); + const handleExport = async () => { + if (!elementRef.current) return; + + try { + // Get SVG element + const svgElement = elementRef.current.querySelector("svg"); + if (!svgElement) throw new Error("No SVG found"); + + // Get SVG viewBox dimensions + const viewBox = svgElement.getAttribute("viewBox")?.split(" ").map(Number) || [ + 0, 0, 0, 0, + ]; + const [, , viewBoxWidth, viewBoxHeight] = viewBox; + + // Create canvas with viewBox dimensions + const canvas = document.createElement("canvas"); + const scale = 2; // For better resolution + canvas.width = viewBoxWidth * scale; + canvas.height = viewBoxHeight * scale; + const ctx = canvas.getContext("2d"); + if (!ctx) throw new Error("Failed to get canvas context"); + + // Convert SVG to data URL + const svgData = new XMLSerializer().serializeToString(svgElement); + const svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" }); + const svgUrl = URL.createObjectURL(svgBlob); + + // Create and load image + const img = new Image(); + img.src = svgUrl; + + await new Promise((resolve, reject) => { + img.onload = () => { + // Scale context for better resolution + ctx.scale(scale, scale); + ctx.drawImage(img, 0, 0, viewBoxWidth, viewBoxHeight); + + canvas.toBlob((blob) => { + if (!blob) { + reject(new Error("Failed to create blob")); + return; + } + + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `mermaid-diagram-${Date.now()}.png`; + a.click(); + + // Cleanup + URL.revokeObjectURL(url); + URL.revokeObjectURL(svgUrl); + resolve(true); + }, "image/png"); + }; + + img.onerror = () => reject(new Error("Failed to load SVG")); + }); + } catch (error) { + console.error("Error exporting diagram:", error); + setMermaidError("Failed to export diagram"); + } + }; + useEffect(() => { - console.log("Rendering mermaid chart:", chart); if (elementRef.current) { elementRef.current.removeAttribute("data-processed"); @@ -79,6 +143,12 @@ const Mermaid: React.FC = ({ chart }) => { {chart}
)} + {!mermaidError && ( + + )}
); }; From 1b5826d8b6540aba6068d162c54923cc7e72101a Mon Sep 17 00:00:00 2001 From: Debanjum Date: Thu, 9 Jan 2025 02:50:52 +0700 Subject: [PATCH 06/33] Support using Embeddings Model exposed via OpenAI (compatible) API --- src/khoj/configure.py | 1 + .../commands/change_default_model.py | 5 +- ...nfig_embeddings_inference_endpoint_type.py | 29 +++++++ src/khoj/database/models/__init__.py | 9 +++ src/khoj/processor/embeddings.py | 76 +++++++++++++------ 5 files changed, 93 insertions(+), 27 deletions(-) create mode 100644 src/khoj/database/migrations/0079_searchmodelconfig_embeddings_inference_endpoint_type.py diff --git a/src/khoj/configure.py b/src/khoj/configure.py index 06b5b497..5fc60fb6 100644 --- a/src/khoj/configure.py +++ b/src/khoj/configure.py @@ -249,6 +249,7 @@ def configure_server( model.bi_encoder, model.embeddings_inference_endpoint, model.embeddings_inference_endpoint_api_key, + model.embeddings_inference_endpoint_type, query_encode_kwargs=model.bi_encoder_query_encode_config, docs_encode_kwargs=model.bi_encoder_docs_encode_config, model_kwargs=model.bi_encoder_model_config, diff --git a/src/khoj/database/management/commands/change_default_model.py b/src/khoj/database/management/commands/change_default_model.py index d55fd44e..43111dd9 100644 --- a/src/khoj/database/management/commands/change_default_model.py +++ b/src/khoj/database/management/commands/change_default_model.py @@ -3,11 +3,11 @@ from typing import List from django.core.management.base import BaseCommand from django.db import transaction -from django.db.models import Count, Q +from django.db.models import Q from tqdm import tqdm from khoj.database.adapters import get_default_search_model -from khoj.database.models import Agent, Entry, KhojUser, SearchModelConfig +from khoj.database.models import Entry, SearchModelConfig from khoj.processor.embeddings import EmbeddingsModel logging.basicConfig(level=logging.INFO) @@ -74,6 +74,7 @@ class Command(BaseCommand): model.bi_encoder, model.embeddings_inference_endpoint, model.embeddings_inference_endpoint_api_key, + model.embeddings_inference_endpoint_type, query_encode_kwargs=model.bi_encoder_query_encode_config, docs_encode_kwargs=model.bi_encoder_docs_encode_config, model_kwargs=model.bi_encoder_model_config, diff --git a/src/khoj/database/migrations/0079_searchmodelconfig_embeddings_inference_endpoint_type.py b/src/khoj/database/migrations/0079_searchmodelconfig_embeddings_inference_endpoint_type.py new file mode 100644 index 00000000..a05668da --- /dev/null +++ b/src/khoj/database/migrations/0079_searchmodelconfig_embeddings_inference_endpoint_type.py @@ -0,0 +1,29 @@ +# Generated by Django 5.0.10 on 2025-01-08 15:09 + +from django.db import migrations, models + + +def set_endpoint_type(apps, schema_editor): + SearchModelConfig = apps.get_model("database", "SearchModelConfig") + SearchModelConfig.objects.filter(embeddings_inference_endpoint__isnull=False).exclude( + embeddings_inference_endpoint="" + ).update(embeddings_inference_endpoint_type="huggingface") + + +class Migration(migrations.Migration): + dependencies = [ + ("database", "0078_khojuser_email_verification_code_expiry"), + ] + + operations = [ + migrations.AddField( + model_name="searchmodelconfig", + name="embeddings_inference_endpoint_type", + field=models.CharField( + choices=[("huggingface", "Huggingface"), ("openai", "Openai"), ("local", "Local")], + default="local", + max_length=200, + ), + ), + migrations.RunPython(set_endpoint_type, reverse_code=migrations.RunPython.noop), + ] diff --git a/src/khoj/database/models/__init__.py b/src/khoj/database/models/__init__.py index 68fae434..29dc5e58 100644 --- a/src/khoj/database/models/__init__.py +++ b/src/khoj/database/models/__init__.py @@ -481,6 +481,11 @@ class SearchModelConfig(DbBaseModel): class ModelType(models.TextChoices): TEXT = "text" + class ApiType(models.TextChoices): + HUGGINGFACE = "huggingface" + OPENAI = "openai" + LOCAL = "local" + # This is the model name exposed to users on their settings page name = models.CharField(max_length=200, default="default") # Type of content the model can generate embeddings for @@ -501,6 +506,10 @@ class SearchModelConfig(DbBaseModel): embeddings_inference_endpoint = models.CharField(max_length=200, default=None, null=True, blank=True) # Inference server API Key to use for embeddings inference. Bi-encoder model should be hosted on this server embeddings_inference_endpoint_api_key = models.CharField(max_length=200, default=None, null=True, blank=True) + # Inference server API type to use for embeddings inference. + embeddings_inference_endpoint_type = models.CharField( + max_length=200, choices=ApiType.choices, default=ApiType.LOCAL + ) # Inference server API endpoint to use for embeddings inference. Cross-encoder model should be hosted on this server cross_encoder_inference_endpoint = models.CharField(max_length=200, default=None, null=True, blank=True) # Inference server API Key to use for embeddings inference. Cross-encoder model should be hosted on this server diff --git a/src/khoj/processor/embeddings.py b/src/khoj/processor/embeddings.py index b224e7f5..0e7b6657 100644 --- a/src/khoj/processor/embeddings.py +++ b/src/khoj/processor/embeddings.py @@ -1,6 +1,8 @@ import logging from typing import List +from urllib.parse import urlparse +import openai import requests import tqdm from sentence_transformers import CrossEncoder, SentenceTransformer @@ -13,7 +15,14 @@ from tenacity import ( ) from torch import nn -from khoj.utils.helpers import fix_json_dict, get_device, merge_dicts, timer +from khoj.database.models import SearchModelConfig +from khoj.utils.helpers import ( + fix_json_dict, + get_device, + get_openai_client, + merge_dicts, + timer, +) from khoj.utils.rawconfig import SearchResponse logger = logging.getLogger(__name__) @@ -25,6 +34,7 @@ class EmbeddingsModel: model_name: str = "thenlper/gte-small", embeddings_inference_endpoint: str = None, embeddings_inference_endpoint_api_key: str = None, + embeddings_inference_endpoint_type=SearchModelConfig.ApiType.LOCAL, query_encode_kwargs: dict = {}, docs_encode_kwargs: dict = {}, model_kwargs: dict = {}, @@ -37,15 +47,16 @@ class EmbeddingsModel: self.model_name = model_name self.inference_endpoint = embeddings_inference_endpoint self.api_key = embeddings_inference_endpoint_api_key - with timer(f"Loaded embedding model {self.model_name}", logger): - self.embeddings_model = SentenceTransformer(self.model_name, **self.model_kwargs) - - def inference_server_enabled(self) -> bool: - return self.api_key is not None and self.inference_endpoint is not None + self.inference_endpoint_type = embeddings_inference_endpoint_type + if self.inference_endpoint_type == SearchModelConfig.ApiType.LOCAL: + with timer(f"Loaded embedding model {self.model_name}", logger): + self.embeddings_model = SentenceTransformer(self.model_name, **self.model_kwargs) def embed_query(self, query): - if self.inference_server_enabled(): - return self.embed_with_api([query])[0] + if self.inference_endpoint_type == SearchModelConfig.ApiType.HUGGINGFACE: + return self.embed_with_hf([query])[0] + elif self.inference_endpoint_type == SearchModelConfig.ApiType.OPENAI: + return self.embed_with_openai([query])[0] return self.embeddings_model.encode([query], **self.query_encode_kwargs)[0] @retry( @@ -54,7 +65,7 @@ class EmbeddingsModel: stop=stop_after_attempt(5), before_sleep=before_sleep_log(logger, logging.DEBUG), ) - def embed_with_api(self, docs): + def embed_with_hf(self, docs): payload = {"inputs": docs} headers = { "Authorization": f"Bearer {self.api_key}", @@ -71,23 +82,38 @@ class EmbeddingsModel: raise e return response.json()["embeddings"] + @retry( + retry=retry_if_exception_type(requests.exceptions.HTTPError), + wait=wait_random_exponential(multiplier=1, max=10), + stop=stop_after_attempt(5), + before_sleep=before_sleep_log(logger, logging.DEBUG), + ) + def embed_with_openai(self, docs): + client = get_openai_client(self.api_key, self.inference_endpoint) + response = client.embeddings.create(input=docs, model=self.model_name, encoding_format="float") + return [item.embedding for item in response.data] + def embed_documents(self, docs): - if self.inference_server_enabled(): - if "huggingface" not in self.inference_endpoint: - logger.warning( - f"Unsupported inference endpoint: {self.inference_endpoint}. Only HuggingFace supported. Generating embeddings on device instead." - ) - return self.embeddings_model.encode(docs, **self.docs_encode_kwargs).tolist() - # break up the docs payload in chunks of 1000 to avoid hitting rate limits - embeddings = [] - with tqdm.tqdm(total=len(docs)) as pbar: - for i in range(0, len(docs), 1000): - docs_to_embed = docs[i : i + 1000] - generated_embeddings = self.embed_with_api(docs_to_embed) - embeddings += generated_embeddings - pbar.update(1000) - return embeddings - return self.embeddings_model.encode(docs, **self.docs_encode_kwargs).tolist() if docs else [] + if self.inference_endpoint_type == SearchModelConfig.ApiType.LOCAL: + return self.embeddings_model.encode(docs, **self.docs_encode_kwargs).tolist() if docs else [] + elif self.inference_endpoint_type == SearchModelConfig.ApiType.HUGGINGFACE: + embed_with_api = self.embed_with_hf + elif self.inference_endpoint_type == SearchModelConfig.ApiType.OPENAI: + embed_with_api = self.embed_with_openai + else: + logger.warning( + f"Unsupported inference endpoint: {self.inference_endpoint_type}. Generating embeddings locally instead." + ) + return self.embeddings_model.encode(docs, **self.docs_encode_kwargs).tolist() + # break up the docs payload in chunks of 1000 to avoid hitting rate limits + embeddings = [] + with tqdm.tqdm(total=len(docs)) as pbar: + for i in range(0, len(docs), 1000): + docs_to_embed = docs[i : i + 1000] + generated_embeddings = embed_with_api(docs_to_embed) + embeddings += generated_embeddings + pbar.update(1000) + return embeddings class CrossEncoderModel: From f398e1eb0c4b1a349a471485c7d8bd096a6cb53b Mon Sep 17 00:00:00 2001 From: sabaimran Date: Fri, 10 Jan 2025 21:46:39 -0800 Subject: [PATCH 07/33] Add codeblock rendering for the mermaidjs diagram in obsidian --- src/interface/obsidian/src/chat_view.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/interface/obsidian/src/chat_view.ts b/src/interface/obsidian/src/chat_view.ts index 86d5e1f9..5097dc2d 100644 --- a/src/interface/obsidian/src/chat_view.ts +++ b/src/interface/obsidian/src/chat_view.ts @@ -487,7 +487,8 @@ export class KhojChatView extends KhojPaneView { inferredQueries?: string[], conversationId?: string, images?: string[], - excalidrawDiagram?: string + excalidrawDiagram?: string, + mermaidjsDiagram?: string ) { if (!message) return; @@ -496,8 +497,9 @@ export class KhojChatView extends KhojPaneView { intentType?.includes("text-to-image") || intentType === "excalidraw" || (images && images.length > 0) || + mermaidjsDiagram || excalidrawDiagram) { - let imageMarkdown = this.generateImageMarkdown(message, intentType ?? "", inferredQueries, conversationId, images, excalidrawDiagram); + let imageMarkdown = this.generateImageMarkdown(message, intentType ?? "", inferredQueries, conversationId, images, excalidrawDiagram, mermaidjsDiagram); chatMessageEl = this.renderMessage(chatEl, imageMarkdown, sender, dt); } else { chatMessageEl = this.renderMessage(chatEl, message, sender, dt); @@ -517,7 +519,7 @@ export class KhojChatView extends KhojPaneView { chatMessageBodyEl.appendChild(this.createReferenceSection(references)); } - generateImageMarkdown(message: string, intentType: string, inferredQueries?: string[], conversationId?: string, images?: string[], excalidrawDiagram?: string): string { + generateImageMarkdown(message: string, intentType: string, inferredQueries?: string[], conversationId?: string, images?: string[], excalidrawDiagram?: string, mermaidjsDiagram?: string): string { let imageMarkdown = ""; if (intentType === "text-to-image") { imageMarkdown = `![](data:image/png;base64,${message})`; @@ -529,6 +531,8 @@ export class KhojChatView extends KhojPaneView { const domain = this.setting.khojUrl.endsWith("/") ? this.setting.khojUrl : `${this.setting.khojUrl}/`; const redirectMessage = `Hey, I'm not ready to show you diagrams yet here. But you can view it in ${domain}chat?conversationId=${conversationId}`; imageMarkdown = redirectMessage; + } else if (mermaidjsDiagram) { + imageMarkdown = "```mermaid\n" + mermaidjsDiagram + "\n```"; } else if (images && images.length > 0) { for (let image of images) { if (image.startsWith("https://")) { @@ -908,6 +912,7 @@ export class KhojChatView extends KhojPaneView { chatBodyEl.dataset.conversationId ?? "", chatLog.images, chatLog.excalidrawDiagram, + chatLog.mermaidjsDiagram, ); // push the user messages to the chat history if (chatLog.by === "you") { @@ -1012,7 +1017,7 @@ export class KhojChatView extends KhojPaneView { } handleJsonResponse(jsonData: any): void { - if (jsonData.image || jsonData.detail || jsonData.images || jsonData.excalidrawDiagram) { + if (jsonData.image || jsonData.detail || jsonData.images || jsonData.mermaidjsDiagram) { this.chatMessageState.rawResponse = this.handleImageResponse(jsonData, this.chatMessageState.rawResponse); } else if (jsonData.response) { this.chatMessageState.rawResponse = jsonData.response; @@ -1407,6 +1412,8 @@ export class KhojChatView extends KhojPaneView { const domain = this.setting.khojUrl.endsWith("/") ? this.setting.khojUrl : `${this.setting.khojUrl}/`; const redirectMessage = `Hey, I'm not ready to show you diagrams yet here. But you can view it in ${domain}`; rawResponse += redirectMessage; + } else if (imageJson.mermaidjsDiagram) { + rawResponse += imageJson.mermaidjsDiagram; } // If response has detail field, response is an error message. From be4b091a21cbd861ce21d3830be462dee53233e8 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Fri, 10 Jan 2025 21:52:52 -0800 Subject: [PATCH 08/33] Add new line to styles.css --- src/interface/obsidian/styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/obsidian/styles.css b/src/interface/obsidian/styles.css index 23113c90..f7c067ed 100644 --- a/src/interface/obsidian/styles.css +++ b/src/interface/obsidian/styles.css @@ -858,4 +858,4 @@ img.copy-icon { 100% { transform: rotate(360deg); } -} \ No newline at end of file +} From 1a00540ee94473b11ec51d0c532f991448764dff Mon Sep 17 00:00:00 2001 From: sabaimran Date: Sun, 12 Jan 2025 22:36:31 -0800 Subject: [PATCH 09/33] Improve error handling in mermaid chart rendering --- .../web/app/components/mermaid/mermaid.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/interface/web/app/components/mermaid/mermaid.tsx b/src/interface/web/app/components/mermaid/mermaid.tsx index 14c71d99..d73a4447 100644 --- a/src/interface/web/app/components/mermaid/mermaid.tsx +++ b/src/interface/web/app/components/mermaid/mermaid.tsx @@ -117,7 +117,24 @@ const Mermaid: React.FC = ({ chart }) => { .then(() => { setMermaidError(null); }) - .catch((error) => {}); + .catch((error) => { + let errorMessage; + try { + errorMessage = typeof error === "string" ? JSON.parse(error) : error; + } catch (e) { + errorMessage = error?.toString() || "Unknown error"; + } + + console.log("Mermaid error message:", errorMessage); + + if (errorMessage.str !== "element is null") { + setMermaidError( + "Something went wrong while rendering the diagram. Please try again later or downvote the message if the issue persists.", + ); + } else { + setMermaidError(null); + } + }); } }, [chart]); From 24ab8450baffd74e4bbfa9f39b0a2d92ff495446 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sun, 12 Jan 2025 21:32:07 +0700 Subject: [PATCH 10/33] Handle scenario where read chat stream error is not json on web app --- src/interface/web/app/chat/page.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/interface/web/app/chat/page.tsx b/src/interface/web/app/chat/page.tsx index ff7cb796..824a7e4c 100644 --- a/src/interface/web/app/chat/page.tsx +++ b/src/interface/web/app/chat/page.tsx @@ -354,7 +354,15 @@ export default function Chat() { try { await readChatStream(response); } catch (err) { - const apiError = await response.json(); + let apiError; + try { + apiError = await response.json(); + } catch (err) { + // Error reading API error response + apiError = { + streamError: "Error reading API error response stream. Expected JSON response.", + }; + } console.error(apiError); // Retrieve latest message being processed const currentMessage = messages.find((message) => !message.completed); @@ -365,7 +373,9 @@ export default function Chat() { const errorName = (err as Error).name; if (errorMessage.includes("Error in input stream")) currentMessage.rawResponse = `Woops! The connection broke while I was writing my thoughts down. Maybe try again in a bit or dislike this message if the issue persists?`; - else if (response.status === 429) { + else if (apiError.streamError) { + currentMessage.rawResponse = `Umm, not sure what just happened but I lost my train of thought. Could you try again or ask my developers to look into this if the issue persists? They can be contacted at the Khoj Github, Discord or team@khoj.dev.`; + } else if (response.status === 429) { "detail" in apiError ? (currentMessage.rawResponse = `${apiError.detail}`) : (currentMessage.rawResponse = `I'm a bit overwhelmed at the moment. Could you try again in a bit or dislike this message if the issue persists?`); From 9355381facd403a9e044db367d38a3ab6dcc5668 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sun, 12 Jan 2025 21:33:30 +0700 Subject: [PATCH 11/33] Catch error in call to data sources, output format selection tool AI Previously if the call to this tool AI failed, the API call would non-gracefully fail on server. This would leave the client hanging in a wierd state (e.g with spinner running on web app with no indication of issue). Also do not show filters in query debug log lines when no filters in query --- src/khoj/routers/api.py | 3 ++- src/khoj/routers/api_chat.py | 25 +++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/khoj/routers/api.py b/src/khoj/routers/api.py index a29e993a..d2df38a3 100644 --- a/src/khoj/routers/api.py +++ b/src/khoj/routers/api.py @@ -392,7 +392,8 @@ async def extract_references_and_questions( filters_in_query += " ".join([f'file:"{filter}"' for filter in conversation.file_filters]) using_offline_chat = False - logger.debug(f"Filters in query: {filters_in_query}") + if is_none_or_empty(filters_in_query): + logger.debug(f"Filters in query: {filters_in_query}") personality_context = prompts.personality_context.format(personality=agent.personality) if agent else "" diff --git a/src/khoj/routers/api_chat.py b/src/khoj/routers/api_chat.py index 1f32ffda..5e50393d 100644 --- a/src/khoj/routers/api_chat.py +++ b/src/khoj/routers/api_chat.py @@ -785,16 +785,21 @@ async def chat( program_execution_context: List[str] = [] if conversation_commands == [ConversationCommand.Default]: - chosen_io = await aget_data_sources_and_output_format( - q, - meta_log, - is_automated_task, - user=user, - query_images=uploaded_images, - agent=agent, - query_files=attached_file_context, - tracer=tracer, - ) + try: + chosen_io = await aget_data_sources_and_output_format( + q, + meta_log, + is_automated_task, + user=user, + query_images=uploaded_images, + agent=agent, + query_files=attached_file_context, + tracer=tracer, + ) + except ValueError as e: + logger.error(f"Error getting data sources and output format: {e}. Falling back to default.") + conversation_commands = [ConversationCommand.General] + conversation_commands = chosen_io.get("sources") + [chosen_io.get("output")] # If we're doing research, we don't want to do anything else From 85c537a1de1e2d153600a23399931d4386f2f2ef Mon Sep 17 00:00:00 2001 From: Debanjum Date: Mon, 13 Jan 2025 20:25:40 +0700 Subject: [PATCH 12/33] Set default PORT arg in Dockerfile to default Khoj port, 42110 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fab572cc..f7f67e9e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,6 +58,6 @@ RUN cd src && python3 khoj/manage.py collectstatic --noinput # Run the Application # There are more arguments required for the application to run, # but those should be passed in through the docker-compose.yml file. -ARG PORT +ARG PORT=42110 EXPOSE ${PORT} ENTRYPOINT ["python3", "src/khoj/main.py"] From 92a1ec7afcc6767ad3c9d9de5930c55497b4f495 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Mon, 13 Jan 2025 21:03:39 +0700 Subject: [PATCH 13/33] Do not auto restart khoj docker services by default Let folks who want to add that, add it manually if they want to. It creates too much noise for folks having trouble with self-host setup --- docker-compose.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index da25558e..10933637 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,6 @@ services: database: image: ankane/pgvector - restart: always environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres @@ -15,10 +14,8 @@ services: retries: 5 sandbox: image: ghcr.io/khoj-ai/terrarium:latest - restart: unless-stopped search: image: docker.io/searxng/searxng:latest - restart: unless-stopped volumes: - khoj_search:/etc/searxng environment: @@ -29,7 +26,6 @@ services: condition: service_healthy # Use the following line to use the latest version of khoj. Otherwise, it will build from source. Set this to ghcr.io/khoj-ai/khoj-cloud:latest if you want to use the prod image. image: ghcr.io/khoj-ai/khoj:latest - restart: unless-stopped # Uncomment the following line to build from source. This will take a few minutes. Comment the next two lines out if you want to use the official image. # build: # context: . From a6bf6803b6210c4c9291c9ddebc045bd9d0abceb Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 15 Jan 2025 17:30:18 +0700 Subject: [PATCH 14/33] Add docs on how to add, edit search model configs when self-hosting --- documentation/docs/features/search.md | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/documentation/docs/features/search.md b/documentation/docs/features/search.md index 810a886b..70410f67 100644 --- a/documentation/docs/features/search.md +++ b/documentation/docs/features/search.md @@ -15,3 +15,37 @@ Take advantage of super fast search to find relevant notes and documents from yo ### Demo ![](/img/search_agents_markdown.png ':size=400px') + + +### Implementation Overview +A bi-encoder models is used to create meaning vectors (aka vector embeddings) of your documents and search queries. +1. When you sync you documents with Khoj, it uses the bi-encoder model to create and store meaning vectors of (chunks of) your documents +2. When you initiate a natural language search the bi-encoder model converts your query into a meaning vector and finds the most relevant document chunks for that query by comparing their meaning vectors. +3. The slower but higher-quality cross-encoder model is than used to re-rank these documents for your given query. + +### Setup (Self-Hosting) +You are **not required** to configure the search model config when self-hosting. Khoj sets up decent default local search model config for general use. + +You may want to configure this if you need better multi-lingual search, want to experiment with different, newer models or the default models do not work for your use-case. + +You can use bi-encoder models downloaded locally [from Huggingface](https://huggingface.co/models?library=sentence-transformers), served via the [HuggingFace Inference API](https://endpoints.huggingface.co/), OpenAI API, Azure OpenAI API or any OpenAI Compatible API like Ollama, LiteLLM etc. Follow the steps below to configure your search model: + +1. Open the [SearchModelConfig](http://localhost:42110/server/admin/database/searchmodelconfig/) page on your Khoj admin panel. +2. Hit the Plus button to add a new model config or click the id of an existing model config to edit it. +3. Set the `biencoder` field to the name of the bi-encoder model supported [locally](https://huggingface.co/models?library=sentence-transformers) or via the API you configure. +4. Set the `Embeddings inference endpoint api key` to your OpenAI API key and `Embeddings inference endpoint type` to `OpenAI` to use an OpenAI embedding model. +5. Also set the `Embeddings inference endpoint` to your Azure OpenAI or OpenAI compatible API URL to use the model via those APIs. +6. Ensure the search model config you want to use is the **only one** that has `name` field set to `default`[^1]. +7. Save the search model configs and restart your Khoj server to start using your new, updated search config. + +:::info +You will need to re-index all your documents if you want to use a different bi-encoder model. +::: + +:::info +You may need to tune the `Bi encoder confidence threshold` field for each bi-encoder to get appropriate number of documents for chat with your Knowledge base. + +Confidence here is a normalized measure of semantic distance between your query and documents. The confidence threshold limits the documents returned to chat that fall within the distance specified in this field. It can take values between 0.0 (exact overlap) and 1.0 (no meaning overlap). +::: + +[^1]: Khoj uses the first search model config named `default` it finds on startup as the search model config for that session From 24204873c862511a4e5ba7f91b275af173ef789d Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 15 Jan 2025 17:48:29 +0700 Subject: [PATCH 15/33] Use same openai base url env var name as the official openai client This eases re-use of the OpenAI API across all openai clients, including chat, image generation, speech to text. Resolves #1085 --- docker-compose.yml | 2 +- documentation/docs/advanced/ollama.mdx | 6 +++--- documentation/docs/get-started/setup.mdx | 6 +++--- src/khoj/configure.py | 2 +- src/khoj/utils/initialization.py | 12 ++++++------ 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 10933637..053dbbbe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: - KHOJ_SEARXNG_URL=http://search:8080 # Uncomment line below to use with Ollama running on your local machine at localhost:11434. # Change URL to use with other OpenAI API compatible providers like VLLM, LMStudio etc. - # - OPENAI_API_BASE=http://host.docker.internal:11434/v1/ + # - OPENAI_BASE_URL=http://host.docker.internal:11434/v1/ # # Uncomment appropriate lines below to use chat models by OpenAI, Anthropic, Google. # Ensure you set your provider specific API keys. diff --git a/documentation/docs/advanced/ollama.mdx b/documentation/docs/advanced/ollama.mdx index 486357e8..1140f33b 100644 --- a/documentation/docs/advanced/ollama.mdx +++ b/documentation/docs/advanced/ollama.mdx @@ -32,7 +32,7 @@ Restart your Khoj server after first run or update to the settings below to ensu ```bash ollama pull llama3.1 ``` - 3. Uncomment `OPENAI_API_BASE` environment variable in your downloaded Khoj [docker-compose.yml](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml#:~:text=OPENAI_API_BASE) + 3. Uncomment `OPENAI_BASE_URL` environment variable in your downloaded Khoj [docker-compose.yml](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml#:~:text=OPENAI_BASE_URL) 4. Start Khoj docker for the first time to automatically integrate and load models from the Ollama running on your host machine ```bash # run below command in the directory where you downloaded the Khoj docker-compose.yml @@ -46,9 +46,9 @@ Restart your Khoj server after first run or update to the settings below to ensu ```bash ollama pull llama3.1 ``` - 3. Set `OPENAI_API_BASE` environment variable to `http://localhost:11434/v1/` in your shell before starting Khoj for the first time + 3. Set `OPENAI_BASE_URL` environment variable to `http://localhost:11434/v1/` in your shell before starting Khoj for the first time ```bash - export OPENAI_API_BASE="http://localhost:11434/v1/" + export OPENAI_BASE_URL="http://localhost:11434/v1/" khoj --anonymous-mode ``` diff --git a/documentation/docs/get-started/setup.mdx b/documentation/docs/get-started/setup.mdx index 17d18aea..7a2cbb16 100644 --- a/documentation/docs/get-started/setup.mdx +++ b/documentation/docs/get-started/setup.mdx @@ -48,7 +48,7 @@ Restart your Khoj server after the first run to ensure all settings are applied 2. Configure the environment variables in the `docker-compose.yml` - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively. - - Uncomment `OPENAI_API_BASE` to use [Ollama](/advanced/ollama?type=first-run&server=docker#setup) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). + - Uncomment `OPENAI_BASE_URL` to use [Ollama](/advanced/ollama?type=first-run&server=docker#setup) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). 3. Start Khoj by running the following command in the same directory as your docker-compose.yml file. ```shell cd ~/.khoj @@ -74,7 +74,7 @@ Restart your Khoj server after the first run to ensure all settings are applied 2. Configure the environment variables in the `docker-compose.yml` - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively. - - Uncomment `OPENAI_API_BASE` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). + - Uncomment `OPENAI_BASE_URL` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). 3. Start Khoj by running the following command in the same directory as your docker-compose.yml file. ```shell # Windows users should use their WSL2 terminal to run these commands @@ -96,7 +96,7 @@ Restart your Khoj server after the first run to ensure all settings are applied 2. Configure the environment variables in the `docker-compose.yml` - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively. - - Uncomment `OPENAI_API_BASE` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). + - Uncomment `OPENAI_BASE_URL` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). 3. Start Khoj by running the following command in the same directory as your docker-compose.yml file. ```shell cd ~/.khoj diff --git a/src/khoj/configure.py b/src/khoj/configure.py index 5fc60fb6..98fb41a0 100644 --- a/src/khoj/configure.py +++ b/src/khoj/configure.py @@ -234,7 +234,7 @@ def configure_server( if ConversationAdapters.has_valid_ai_model_api(): ai_model_api = ConversationAdapters.get_ai_model_api() - state.openai_client = openai.OpenAI(api_key=ai_model_api.api_key) + state.openai_client = openai.OpenAI(api_key=ai_model_api.api_key, base_url=ai_model_api.api_base_url) # Initialize Search Models from Config and initialize content try: diff --git a/src/khoj/utils/initialization.py b/src/khoj/utils/initialization.py index 83062a21..6c0d6d42 100644 --- a/src/khoj/utils/initialization.py +++ b/src/khoj/utils/initialization.py @@ -43,14 +43,14 @@ def initialization(interactive: bool = True): "🗣️ Configure chat models available to your server. You can always update these at /server/admin using your admin account" ) - openai_api_base = os.getenv("OPENAI_API_BASE") - provider = "Ollama" if openai_api_base and openai_api_base.endswith(":11434/v1/") else "OpenAI" - openai_api_key = os.getenv("OPENAI_API_KEY", "placeholder" if openai_api_base else None) + openai_base_url = os.getenv("OPENAI_BASE_URL") + provider = "Ollama" if openai_base_url and openai_base_url.endswith(":11434/v1/") else "OpenAI" + openai_api_key = os.getenv("OPENAI_API_KEY", "placeholder" if openai_base_url else None) default_chat_models = default_openai_chat_models - if openai_api_base: + if openai_base_url: # Get available chat models from OpenAI compatible API try: - openai_client = openai.OpenAI(api_key=openai_api_key, base_url=openai_api_base) + openai_client = openai.OpenAI(api_key=openai_api_key, base_url=openai_base_url) default_chat_models = [model.id for model in openai_client.models.list()] # Put the available default OpenAI models at the top valid_default_models = [model for model in default_openai_chat_models if model in default_chat_models] @@ -66,7 +66,7 @@ def initialization(interactive: bool = True): ChatModel.ModelType.OPENAI, default_chat_models, default_api_key=openai_api_key, - api_base_url=openai_api_base, + api_base_url=openai_base_url, vision_enabled=True, is_offline=False, interactive=interactive, From 182c49b41c477ac310e04b3532e0e999f06bbb8d Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 15 Jan 2025 17:55:21 +0700 Subject: [PATCH 16/33] Prefer explicitly configured OpenAI API url, key for image gen model Previously we'd use the general openai client, even if the image generation model has a different api key and base url set. This change uses the openai config of the image generation models when set. Otherwise it fallbacks to use the first openai api provider set --- src/khoj/processor/image/generate.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/khoj/processor/image/generate.py b/src/khoj/processor/image/generate.py index a4628115..daf0dbf9 100644 --- a/src/khoj/processor/image/generate.py +++ b/src/khoj/processor/image/generate.py @@ -119,25 +119,27 @@ async def text_to_image( def generate_image_with_openai( improved_image_prompt: str, text_to_image_config: TextToImageModelConfig, text2image_model: str ): - "Generate image using OpenAI API" + "Generate image using OpenAI (compatible) API" - # Get the API key from the user's configuration + # Get the API config from the user's configuration + api_key = None if text_to_image_config.api_key: api_key = text_to_image_config.api_key + openai_client = openai.OpenAI(api_key=api_key) elif text_to_image_config.ai_model_api: api_key = text_to_image_config.ai_model_api.api_key + api_base_url = text_to_image_config.ai_model_api.api_base_url + openai_client = openai.OpenAI(api_key=api_key, base_url=api_base_url) elif state.openai_client: - api_key = state.openai_client.api_key - auth_header = {"Authorization": f"Bearer {api_key}"} if api_key else {} + openai_client = state.openai_client # Generate image using OpenAI API OPENAI_IMAGE_GEN_STYLE = "vivid" - response = state.openai_client.images.generate( + response = openai_client.images.generate( prompt=improved_image_prompt, model=text2image_model, style=OPENAI_IMAGE_GEN_STYLE, response_format="b64_json", - extra_headers=auth_header, ) # Extract the base64 image from the response From f8b887cabdb921912f19500a6bae2b5bcd90b1ec Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 15 Jan 2025 18:31:37 +0700 Subject: [PATCH 17/33] Allow using OpenAI (compatible) API for Speech to Text transcription --- src/khoj/database/adapters/__init__.py | 2 +- ...0_speechtotextmodeloptions_ai_model_api.py | 24 +++++++++++++++++++ src/khoj/database/models/__init__.py | 1 + src/khoj/routers/api.py | 16 ++++++++++--- 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 src/khoj/database/migrations/0080_speechtotextmodeloptions_ai_model_api.py diff --git a/src/khoj/database/adapters/__init__.py b/src/khoj/database/adapters/__init__.py index 89ffdc54..8e595dae 100644 --- a/src/khoj/database/adapters/__init__.py +++ b/src/khoj/database/adapters/__init__.py @@ -1288,7 +1288,7 @@ class ConversationAdapters: @staticmethod async def get_speech_to_text_config(): - return await SpeechToTextModelOptions.objects.filter().afirst() + return await SpeechToTextModelOptions.objects.filter().prefetch_related("ai_model_api").afirst() @staticmethod @arequire_valid_user diff --git a/src/khoj/database/migrations/0080_speechtotextmodeloptions_ai_model_api.py b/src/khoj/database/migrations/0080_speechtotextmodeloptions_ai_model_api.py new file mode 100644 index 00000000..5ed66e16 --- /dev/null +++ b/src/khoj/database/migrations/0080_speechtotextmodeloptions_ai_model_api.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0.10 on 2025-01-15 11:05 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("database", "0079_searchmodelconfig_embeddings_inference_endpoint_type"), + ] + + operations = [ + migrations.AddField( + model_name="speechtotextmodeloptions", + name="ai_model_api", + field=models.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="database.aimodelapi", + ), + ), + ] diff --git a/src/khoj/database/models/__init__.py b/src/khoj/database/models/__init__.py index 29dc5e58..3e693e15 100644 --- a/src/khoj/database/models/__init__.py +++ b/src/khoj/database/models/__init__.py @@ -566,6 +566,7 @@ class SpeechToTextModelOptions(DbBaseModel): model_name = models.CharField(max_length=200, default="base") model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.OFFLINE) + ai_model_api = models.ForeignKey(AiModelApi, on_delete=models.CASCADE, default=None, null=True, blank=True) def __str__(self): return f"{self.model_name} - {self.model_type}" diff --git a/src/khoj/routers/api.py b/src/khoj/routers/api.py index d2df38a3..44375bca 100644 --- a/src/khoj/routers/api.py +++ b/src/khoj/routers/api.py @@ -9,6 +9,7 @@ import uuid from typing import Any, Callable, List, Optional, Set, Union import cron_descriptor +import openai import pytz from apscheduler.job import Job from apscheduler.triggers.cron import CronTrigger @@ -264,12 +265,21 @@ async def transcribe( if not speech_to_text_config: # If the user has not configured a speech to text model, return an unsupported on server error status_code = 501 - elif state.openai_client and speech_to_text_config.model_type == SpeechToTextModelOptions.ModelType.OPENAI: - speech2text_model = speech_to_text_config.model_name - user_message = await transcribe_audio(audio_file, speech2text_model, client=state.openai_client) elif speech_to_text_config.model_type == SpeechToTextModelOptions.ModelType.OFFLINE: speech2text_model = speech_to_text_config.model_name user_message = await transcribe_audio_offline(audio_filename, speech2text_model) + elif speech_to_text_config.model_type == SpeechToTextModelOptions.ModelType.OPENAI: + speech2text_model = speech_to_text_config.model_name + if speech_to_text_config.ai_model_api: + api_key = speech_to_text_config.ai_model_api.api_key + api_base_url = speech_to_text_config.ai_model_api.api_base_url + openai_client = openai.OpenAI(api_key=api_key, base_url=api_base_url) + elif state.openai_client: + openai_client = state.openai_client + if openai_client: + user_message = await transcribe_audio(audio_file, speech2text_model, client=openai_client) + else: + status_code = 501 finally: # Close and Delete the temporary audio file audio_file.close() From ed18c04576bdafda87452f51c847cffba829f84e Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 15 Jan 2025 18:37:54 +0700 Subject: [PATCH 18/33] Fix wrapping base64 generated image for inline display Resolves #1082 --- src/khoj/processor/image/generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/khoj/processor/image/generate.py b/src/khoj/processor/image/generate.py index daf0dbf9..252e61eb 100644 --- a/src/khoj/processor/image/generate.py +++ b/src/khoj/processor/image/generate.py @@ -111,7 +111,7 @@ async def text_to_image( image_url = upload_image(webp_image_bytes, user.uuid) if not image_url: - image = base64.b64encode(webp_image_bytes).decode("utf-8") + image = f"data:image/webp;base64,{base64.b64encode(webp_image_bytes).decode('utf-8')}" yield image_url or image, status_code, image_prompt From 2e585efd2fa76cb608d23dbd1282819c74a855a4 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 15 Jan 2025 19:43:02 +0700 Subject: [PATCH 19/33] Fix end with newline styling issue in style.css to pass lint checks --- src/interface/obsidian/styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/obsidian/styles.css b/src/interface/obsidian/styles.css index 23113c90..f7c067ed 100644 --- a/src/interface/obsidian/styles.css +++ b/src/interface/obsidian/styles.css @@ -858,4 +858,4 @@ img.copy-icon { 100% { transform: rotate(360deg); } -} \ No newline at end of file +} From e2b2b3415e00f42462b99c37912c9bd2570b30ea Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 15 Jan 2025 20:52:26 +0700 Subject: [PATCH 20/33] Fix handling of inline base64 images by Obsidian, Desktop clients Fix for #1082 pushed down adding the `data:image/webp;base64' prefix of the base64 images to the server image gen API. But the code on the Obsidian and Desktop client still add these prefixes. This change stops the Desktop, Obsidian clients from adding the prefix as it is being handled by the API now. It should resolve showing images inline in those clients as well --- src/interface/desktop/chatutils.js | 4 ++-- src/interface/obsidian/src/chat_view.ts | 22 +++++----------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/interface/desktop/chatutils.js b/src/interface/desktop/chatutils.js index 48fb72c3..7fb05e1a 100644 --- a/src/interface/desktop/chatutils.js +++ b/src/interface/desktop/chatutils.js @@ -229,7 +229,7 @@ function generateImageMarkdown(message, intentType, inferredQueries=null) { //sa } else if (intentType === "text-to-image2") { imageMarkdown = `![](${message})`; } else if (intentType === "text-to-image-v3") { - imageMarkdown = `![](data:image/webp;base64,${message})`; + imageMarkdown = `![](${message})`; } const inferredQuery = inferredQueries?.[0]; if (inferredQuery) { @@ -423,7 +423,7 @@ function handleImageResponse(imageJson, rawResponse) { } else if (imageJson.intentType === "text-to-image2") { rawResponse += `![generated_image](${imageJson.image})`; } else if (imageJson.intentType === "text-to-image-v3") { - rawResponse = `![](data:image/webp;base64,${imageJson.image})`; + rawResponse = `![](${imageJson.image})`; } else if (imageJson.intentType === "excalidraw") { const redirectMessage = `Hey, I'm not ready to show you diagrams yet here. But you can view it in the web app`; rawResponse += redirectMessage; diff --git a/src/interface/obsidian/src/chat_view.ts b/src/interface/obsidian/src/chat_view.ts index 86d5e1f9..e25a673b 100644 --- a/src/interface/obsidian/src/chat_view.ts +++ b/src/interface/obsidian/src/chat_view.ts @@ -524,21 +524,14 @@ export class KhojChatView extends KhojPaneView { } else if (intentType === "text-to-image2") { imageMarkdown = `![](${message})`; } else if (intentType === "text-to-image-v3") { - imageMarkdown = `![](data:image/webp;base64,${message})`; + imageMarkdown = `![](${message})`; } else if (intentType === "excalidraw" || excalidrawDiagram) { const domain = this.setting.khojUrl.endsWith("/") ? this.setting.khojUrl : `${this.setting.khojUrl}/`; const redirectMessage = `Hey, I'm not ready to show you diagrams yet here. But you can view it in ${domain}chat?conversationId=${conversationId}`; imageMarkdown = redirectMessage; } else if (images && images.length > 0) { - for (let image of images) { - if (image.startsWith("https://")) { - imageMarkdown += `![](${image})\n\n`; - } else { - imageMarkdown += `![](data:image/png;base64,${image})\n\n`; - } - } - - imageMarkdown += `${message}`; + imageMarkdown += images.map(image => `![](${image})`).join('\n\n'); + imageMarkdown += message; } if (images?.length === 0 && inferredQueries) { @@ -1384,7 +1377,7 @@ export class KhojChatView extends KhojPaneView { } else if (imageJson.intentType === "text-to-image2") { rawResponse += `![generated_image](${imageJson.image})`; } else if (imageJson.intentType === "text-to-image-v3") { - rawResponse = `![](data:image/webp;base64,${imageJson.image})`; + rawResponse = `![generated_image](${imageJson.image})`; } else if (imageJson.intentType === "excalidraw") { const domain = this.setting.khojUrl.endsWith("/") ? this.setting.khojUrl : `${this.setting.khojUrl}/`; const redirectMessage = `Hey, I'm not ready to show you diagrams yet here. But you can view it in ${domain}`; @@ -1396,12 +1389,7 @@ export class KhojChatView extends KhojPaneView { } else if (imageJson.images) { // If response has images field, response is a list of generated images. imageJson.images.forEach((image: any) => { - - if (image.startsWith("http")) { - rawResponse += `![generated_image](${image})\n\n`; - } else { - rawResponse += `![generated_image](data:image/png;base64,${image})\n\n`; - } + rawResponse += `![generated_image](${image})\n\n`; }); } else if (imageJson.excalidrawDiagram) { const domain = this.setting.khojUrl.endsWith("/") ? this.setting.khojUrl : `${this.setting.khojUrl}/`; From a649b036589a9bd4f2f70fed746e60710b91ca77 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Thu, 16 Jan 2025 11:29:04 +0700 Subject: [PATCH 21/33] Support online search using Google Search API --- src/khoj/processor/tools/online_search.py | 74 ++++++++++++++++++++--- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/src/khoj/processor/tools/online_search.py b/src/khoj/processor/tools/online_search.py index 5e73fb07..33cc3056 100644 --- a/src/khoj/processor/tools/online_search.py +++ b/src/khoj/processor/tools/online_search.py @@ -30,6 +30,8 @@ from khoj.utils.rawconfig import LocationData logger = logging.getLogger(__name__) +GOOGLE_SEARCH_API_KEY = os.getenv("GOOGLE_SEARCH_API_KEY") +GOOGLE_SEARCH_ENGINE_ID = os.getenv("GOOGLE_SEARCH_ENGINE_ID") SERPER_DEV_API_KEY = os.getenv("SERPER_DEV_API_KEY") SERPER_DEV_URL = "https://google.serper.dev/search" @@ -96,19 +98,25 @@ async def search_online( yield response_dict return - logger.info(f"🌐 Searching the Internet for {subqueries}") + if GOOGLE_SEARCH_API_KEY and GOOGLE_SEARCH_ENGINE_ID: + search_engine = "Google" + search_func = search_with_google + elif SERPER_DEV_API_KEY: + search_engine = "Serper" + search_func = search_with_serper + elif JINA_API_KEY: + search_engine = "Jina" + search_func = search_with_jina + else: + search_engine = "Searxng" + search_func = search_with_searxng + + logger.info(f"🌐 Searching the Internet with {search_engine} for {subqueries}") if send_status_func: subqueries_str = "\n- " + "\n- ".join(subqueries) async for event in send_status_func(f"**Searching the Internet for**: {subqueries_str}"): yield {ChatEvent.STATUS: event} - if SERPER_DEV_API_KEY: - search_func = search_with_serper - elif JINA_API_KEY: - search_func = search_with_jina - else: - search_func = search_with_searxng - with timer(f"Internet searches for {subqueries} took", logger): search_tasks = [search_func(subquery, location) for subquery in subqueries] search_results = await asyncio.gather(*search_tasks) @@ -195,6 +203,56 @@ async def search_with_searxng(query: str, location: LocationData) -> Tuple[str, return query, {} +async def search_with_google(query: str, location: LocationData) -> Tuple[str, Dict[str, List[Dict]]]: + country_code = location.country_code.lower() if location and location.country_code else "us" + base_url = "https://www.googleapis.com/customsearch/v1" + params = { + "key": GOOGLE_SEARCH_API_KEY, + "cx": GOOGLE_SEARCH_ENGINE_ID, + "q": query, + "cr": f"country{country_code.upper()}", # Country restrict parameter + "gl": country_code, # Geolocation parameter + } + + async with aiohttp.ClientSession() as session: + async with session.get(base_url, params=params) as response: + if response.status != 200: + logger.error(await response.text()) + return query, {} + + json_response = await response.json() + + # Transform Google's response format to match Serper's format + organic_results = [] + if "items" in json_response: + organic_results = [ + { + "title": item.get("title", ""), + "link": item.get("link", ""), + "snippet": item.get("snippet", ""), + "content": None, # Google Search API doesn't provide full content + } + for item in json_response["items"] + ] + + # Format knowledge graph if available + knowledge_graph = {} + if "knowledge_graph" in json_response: + kg = json_response["knowledge_graph"] + knowledge_graph = { + "title": kg.get("name", ""), + "description": kg.get("description", ""), + "type": kg.get("type", ""), + } + + extracted_search_result: Dict[str, Any] = {"organic": organic_results} + + if knowledge_graph: + extracted_search_result["knowledgeGraph"] = knowledge_graph + + return query, extracted_search_result + + async def search_with_serper(query: str, location: LocationData) -> Tuple[str, Dict[str, List[Dict]]]: country_code = location.country_code.lower() if location and location.country_code else "us" payload = json.dumps({"q": query, "gl": country_code}) From 00843f4f2460b912f22d685c9b92e593d55c0a04 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Thu, 16 Jan 2025 12:11:28 +0700 Subject: [PATCH 22/33] Release Khoj version 1.34.0 --- manifest.json | 2 +- src/interface/desktop/package.json | 2 +- src/interface/emacs/khoj.el | 2 +- src/interface/obsidian/manifest.json | 2 +- src/interface/obsidian/package.json | 2 +- src/interface/obsidian/versions.json | 3 ++- src/interface/web/package.json | 2 +- versions.json | 3 ++- 8 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest.json b/manifest.json index 3e5f8331..6c8ad3bf 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "khoj", "name": "Khoj", - "version": "1.33.2", + "version": "1.34.0", "minAppVersion": "0.15.0", "description": "Your Second Brain", "author": "Khoj Inc.", diff --git a/src/interface/desktop/package.json b/src/interface/desktop/package.json index ef28b055..e7d0a4c2 100644 --- a/src/interface/desktop/package.json +++ b/src/interface/desktop/package.json @@ -1,6 +1,6 @@ { "name": "Khoj", - "version": "1.33.2", + "version": "1.34.0", "description": "Your Second Brain", "author": "Khoj Inc. ", "license": "GPL-3.0-or-later", diff --git a/src/interface/emacs/khoj.el b/src/interface/emacs/khoj.el index 828139b0..d832fc51 100644 --- a/src/interface/emacs/khoj.el +++ b/src/interface/emacs/khoj.el @@ -6,7 +6,7 @@ ;; Saba Imran ;; Description: Your Second Brain ;; Keywords: search, chat, ai, org-mode, outlines, markdown, pdf, image -;; Version: 1.33.2 +;; Version: 1.34.0 ;; Package-Requires: ((emacs "27.1") (transient "0.3.0") (dash "2.19.1")) ;; URL: https://github.com/khoj-ai/khoj/tree/master/src/interface/emacs diff --git a/src/interface/obsidian/manifest.json b/src/interface/obsidian/manifest.json index 3e5f8331..6c8ad3bf 100644 --- a/src/interface/obsidian/manifest.json +++ b/src/interface/obsidian/manifest.json @@ -1,7 +1,7 @@ { "id": "khoj", "name": "Khoj", - "version": "1.33.2", + "version": "1.34.0", "minAppVersion": "0.15.0", "description": "Your Second Brain", "author": "Khoj Inc.", diff --git a/src/interface/obsidian/package.json b/src/interface/obsidian/package.json index 76a82635..2ef8b849 100644 --- a/src/interface/obsidian/package.json +++ b/src/interface/obsidian/package.json @@ -1,6 +1,6 @@ { "name": "Khoj", - "version": "1.33.2", + "version": "1.34.0", "description": "Your Second Brain", "author": "Debanjum Singh Solanky, Saba Imran ", "license": "GPL-3.0-or-later", diff --git a/src/interface/obsidian/versions.json b/src/interface/obsidian/versions.json index e7dced26..47ff6efa 100644 --- a/src/interface/obsidian/versions.json +++ b/src/interface/obsidian/versions.json @@ -108,5 +108,6 @@ "1.32.2": "0.15.0", "1.33.0": "0.15.0", "1.33.1": "0.15.0", - "1.33.2": "0.15.0" + "1.33.2": "0.15.0", + "1.34.0": "0.15.0" } diff --git a/src/interface/web/package.json b/src/interface/web/package.json index 9439b401..5aa04ff4 100644 --- a/src/interface/web/package.json +++ b/src/interface/web/package.json @@ -1,6 +1,6 @@ { "name": "khoj-ai", - "version": "1.33.2", + "version": "1.34.0", "private": true, "scripts": { "dev": "next dev", diff --git a/versions.json b/versions.json index e7dced26..47ff6efa 100644 --- a/versions.json +++ b/versions.json @@ -108,5 +108,6 @@ "1.32.2": "0.15.0", "1.33.0": "0.15.0", "1.33.1": "0.15.0", - "1.33.2": "0.15.0" + "1.33.2": "0.15.0", + "1.34.0": "0.15.0" } From 849348e638dc22a9955cbbbf2da6e9b052b2bee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tu=C4=9Fhan=20Belbek?= Date: Thu, 16 Jan 2025 16:03:43 +0100 Subject: [PATCH 23/33] Handle additional HTTP redirect status code 308 in scheduled chat requests (#1088) Closes #1067 --- src/khoj/routers/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/khoj/routers/helpers.py b/src/khoj/routers/helpers.py index 4d545bc8..67b367b0 100644 --- a/src/khoj/routers/helpers.py +++ b/src/khoj/routers/helpers.py @@ -1913,7 +1913,7 @@ def scheduled_chat( raw_response = requests.post(url, headers=headers, json=json_payload, allow_redirects=False) # Handle redirect manually if necessary - if raw_response.status_code in [301, 302]: + if raw_response.status_code in [301, 302, 308]: redirect_url = raw_response.headers["Location"] logger.info(f"Redirecting to {redirect_url}") raw_response = requests.post(redirect_url, headers=headers, json=json_payload) From b8c866014d9a71a88e88d0926201f6fd83dbf796 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Fri, 17 Jan 2025 17:19:59 -0800 Subject: [PATCH 24/33] Improve instruction description for the agent command description for notes --- src/khoj/utils/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/khoj/utils/helpers.py b/src/khoj/utils/helpers.py index 4e16d6b5..e3cab3c7 100644 --- a/src/khoj/utils/helpers.py +++ b/src/khoj/utils/helpers.py @@ -355,7 +355,7 @@ command_descriptions = { command_descriptions_for_agent = { ConversationCommand.General: "Agent can use the agents knowledge base and general knowledge.", - ConversationCommand.Notes: "Agent can search the users knowledge base for information.", + ConversationCommand.Notes: "Agent can search the personal knowledge base for information, as well as its own.", ConversationCommand.Online: "Agent can search the internet for information.", ConversationCommand.Webpage: "Agent can read suggested web pages for information.", ConversationCommand.Summarize: "Agent can read an entire document. Agents knowledge base must be a single document.", From af9e906cb57caf80ba8a3e6ea35978dcee9d206a Mon Sep 17 00:00:00 2001 From: sabaimran Date: Fri, 17 Jan 2025 17:48:42 -0800 Subject: [PATCH 25/33] Use python3 instead of python when running pip install commands in gh actions --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f5dfc6f..c68dbf96 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -72,8 +72,8 @@ jobs: - name: ⬇️ Install pip run: | apt install -y python3-pip - python -m ensurepip --upgrade - python -m pip install --upgrade pip + python3 -m ensurepip --upgrade + python3 -m pip install --upgrade pip - name: ⬇️ Install Application env: From 51f3af11b57995a98d4f7c1fb06ddd5d240e0e22 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sun, 19 Jan 2025 12:26:00 +0700 Subject: [PATCH 26/33] Fix Qwen 2.5 14B model source to use Q4_K_M quantized model The official Qwen2.5 14B model doesn't mention standard quantization suffixes like Q4_K_M, so doesn't work with Khoj --- src/khoj/processor/conversation/utils.py | 2 +- src/khoj/utils/constants.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/khoj/processor/conversation/utils.py b/src/khoj/processor/conversation/utils.py index e8c78c75..75a76918 100644 --- a/src/khoj/processor/conversation/utils.py +++ b/src/khoj/processor/conversation/utils.py @@ -62,7 +62,7 @@ model_to_prompt_size = { "claude-3-5-sonnet-20241022": 60000, "claude-3-5-haiku-20241022": 60000, # Offline Models - "Qwen/Qwen2.5-14B-Instruct-GGUF": 20000, + "bartowski/Qwen2.5-14B-Instruct-GGUF": 20000, "bartowski/Meta-Llama-3.1-8B-Instruct-GGUF": 20000, "bartowski/Llama-3.2-3B-Instruct-GGUF": 20000, "bartowski/gemma-2-9b-it-GGUF": 6000, diff --git a/src/khoj/utils/constants.py b/src/khoj/utils/constants.py index 59534895..6e89594d 100644 --- a/src/khoj/utils/constants.py +++ b/src/khoj/utils/constants.py @@ -15,7 +15,7 @@ default_offline_chat_models = [ "bartowski/Llama-3.2-3B-Instruct-GGUF", "bartowski/gemma-2-9b-it-GGUF", "bartowski/gemma-2-2b-it-GGUF", - "Qwen/Qwen2.5-14B-Instruct-GGUF", + "bartowski/Qwen2.5-14B-Instruct-GGUF", ] default_openai_chat_models = ["gpt-4o-mini", "gpt-4o"] default_gemini_chat_models = ["gemini-1.5-flash", "gemini-1.5-pro"] From 2d4633d298edb1fcc6847818e38982b89f524119 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sun, 19 Jan 2025 13:05:15 +0700 Subject: [PATCH 27/33] Use encoded email, otp in login URL in email & web app sign-in flow Previously emails with url special characters would not get successfully identified for login. Account creation was fine due to email being in POST request body. But login with such emails did not work due to query params not being escaped before being sent to server This change escapes both the code and email in login URL sent to server. So login with emails containing special characters like `email+khoj@gmail.com' works. It fixes both the URL web app sent by web app directly and the magic link sent to users to their email This change also fixes accessibility issue of having a DialogTitle in DialogContent for screen readers. Resolves #1090 --- .../web/app/components/loginPrompt/loginPrompt.tsx | 8 ++++++-- src/khoj/database/admin.py | 6 ++++-- src/khoj/routers/email.py | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/interface/web/app/components/loginPrompt/loginPrompt.tsx b/src/interface/web/app/components/loginPrompt/loginPrompt.tsx index 5cda444a..633d7b41 100644 --- a/src/interface/web/app/components/loginPrompt/loginPrompt.tsx +++ b/src/interface/web/app/components/loginPrompt/loginPrompt.tsx @@ -2,7 +2,7 @@ import styles from "./loginPrompt.module.css"; import { Button } from "@/components/ui/button"; -import { Dialog, DialogContent } from "@/components/ui/dialog"; +import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import Autoplay from "embla-carousel-autoplay"; import { @@ -27,6 +27,7 @@ import { } from "@/components/ui/carousel"; import { Card, CardContent } from "@/components/ui/card"; import { InputOTP, InputOTPGroup, InputOTPSlot } from "@/components/ui/input-otp"; +import * as VisuallyHidden from "@radix-ui/react-visually-hidden"; export interface LoginPromptProps { onOpenChange: (open: boolean) => void; @@ -181,6 +182,9 @@ export default function LoginPrompt(props: LoginPromptProps) { + + Login Dialog +
{useEmailSignIn ? ( = ALLOWED_OTP_ATTEMPTS) { setOTPError("Too many failed attempts. Please try again tomorrow."); diff --git a/src/khoj/database/admin.py b/src/khoj/database/admin.py index a90a339e..322b3afd 100644 --- a/src/khoj/database/admin.py +++ b/src/khoj/database/admin.py @@ -1,6 +1,7 @@ import csv import json from datetime import datetime, timedelta +from urllib.parse import quote from apscheduler.job import Job from django.contrib import admin, messages @@ -154,8 +155,9 @@ class KhojUserAdmin(UserAdmin, unfold_admin.ModelAdmin): for user in queryset: if user.email: host = request.get_host() - unique_id = user.email_verification_code - login_url = f"{host}/auth/magic?code={unique_id}&email={user.email}" + otp = quote(user.email_verification_code) + encoded_email = quote(user.email) + login_url = f"{host}/auth/magic?code={otp}&email={encoded_email}" messages.info(request, f"Email login URL for {user.email}: {login_url}") get_email_login_url.short_description = "Get email login URL" # type: ignore diff --git a/src/khoj/routers/email.py b/src/khoj/routers/email.py index 701db0a6..ce9e0ae6 100644 --- a/src/khoj/routers/email.py +++ b/src/khoj/routers/email.py @@ -1,5 +1,6 @@ import logging import os +from urllib.parse import quote import markdown_it import resend @@ -29,7 +30,7 @@ def is_resend_enabled(): async def send_magic_link_email(email, unique_id, host): - sign_in_link = f"{host}auth/magic?code={unique_id}&email={email}" + sign_in_link = f"{host}auth/magic?code={quote(unique_id)}&email={quote(email)}" if not is_resend_enabled(): logger.debug(f"Email sending disabled. Share this sign-in link with the user: {sign_in_link}") From fde71ded16c07819dda4225a387a1df22b31299a Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sun, 19 Jan 2025 13:44:33 +0700 Subject: [PATCH 28/33] Upgrade web app dependencies --- src/interface/web/package.json | 4 +- src/interface/web/yarn.lock | 116 ++++++++++++++++----------------- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/interface/web/package.json b/src/interface/web/package.json index 5aa04ff4..b7f6bb5d 100644 --- a/src/interface/web/package.json +++ b/src/interface/web/package.json @@ -53,13 +53,13 @@ "eslint-config-next": "14.2.3", "input-otp": "^1.2.4", "intl-tel-input": "^23.8.1", - "katex": "^0.16.10", + "katex": "^0.16.21", "libphonenumber-js": "^1.11.4", "lucide-react": "^0.468.0", "markdown-it": "^14.1.0", "markdown-it-highlightjs": "^4.1.0", "mermaid": "^11.4.1", - "next": "14.2.15", + "next": "14.2.21", "nodemon": "^3.1.3", "postcss": "^8.4.38", "react": "^18", diff --git a/src/interface/web/yarn.lock b/src/interface/web/yarn.lock index 14aec059..05031338 100644 --- a/src/interface/web/yarn.lock +++ b/src/interface/web/yarn.lock @@ -437,10 +437,10 @@ dependencies: langium "3.0.0" -"@next/env@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.15.tgz#06d984e37e670d93ddd6790af1844aeb935f332f" - integrity sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ== +"@next/env@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.21.tgz#09ff0813d29c596397e141205d4f5fd5c236bdd0" + integrity sha512-lXcwcJd5oR01tggjWJ6SrNNYFGuOOMB9c251wUNkjCpkoXOPkDeF/15c3mnVlBqrW4JJXb2kVxDFhC4GduJt2A== "@next/eslint-plugin-next@14.2.3": version "14.2.3" @@ -449,50 +449,50 @@ dependencies: glob "10.3.10" -"@next/swc-darwin-arm64@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz#6386d585f39a1c490c60b72b1f76612ba4434347" - integrity sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA== +"@next/swc-darwin-arm64@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.21.tgz#32a31992aace1440981df9cf7cb3af7845d94fec" + integrity sha512-HwEjcKsXtvszXz5q5Z7wCtrHeTTDSTgAbocz45PHMUjU3fBYInfvhR+ZhavDRUYLonm53aHZbB09QtJVJj8T7g== -"@next/swc-darwin-x64@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz#b7baeedc6a28f7545ad2bc55adbab25f7b45cb89" - integrity sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg== +"@next/swc-darwin-x64@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.21.tgz#5ab4b3f6685b6b52f810d0f5cf6e471480ddffdb" + integrity sha512-TSAA2ROgNzm4FhKbTbyJOBrsREOMVdDIltZ6aZiKvCi/v0UwFmwigBGeqXDA97TFMpR3LNNpw52CbVelkoQBxA== -"@next/swc-linux-arm64-gnu@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz#fa13c59d3222f70fb4cb3544ac750db2c6e34d02" - integrity sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw== +"@next/swc-linux-arm64-gnu@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.21.tgz#8a0e1fa887aef19ca218af2af515d0a5ee67ba3f" + integrity sha512-0Dqjn0pEUz3JG+AImpnMMW/m8hRtl1GQCNbO66V1yp6RswSTiKmnHf3pTX6xMdJYSemf3O4Q9ykiL0jymu0TuA== -"@next/swc-linux-arm64-musl@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz#30e45b71831d9a6d6d18d7ac7d611a8d646a17f9" - integrity sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ== +"@next/swc-linux-arm64-musl@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.21.tgz#ddad844406b42fa8965fe11250abc85c1fe0fd05" + integrity sha512-Ggfw5qnMXldscVntwnjfaQs5GbBbjioV4B4loP+bjqNEb42fzZlAaK+ldL0jm2CTJga9LynBMhekNfV8W4+HBw== -"@next/swc-linux-x64-gnu@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz#5065db17fc86f935ad117483f21f812dc1b39254" - integrity sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA== +"@next/swc-linux-x64-gnu@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.21.tgz#db55fd666f9ba27718f65caa54b622a912cdd16b" + integrity sha512-uokj0lubN1WoSa5KKdThVPRffGyiWlm/vCc/cMkWOQHw69Qt0X1o3b2PyLLx8ANqlefILZh1EdfLRz9gVpG6tg== -"@next/swc-linux-x64-musl@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz#3c4a4568d8be7373a820f7576cf33388b5dab47e" - integrity sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ== +"@next/swc-linux-x64-musl@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.21.tgz#dddb850353624efcd58c4c4e30ad8a1aab379642" + integrity sha512-iAEBPzWNbciah4+0yI4s7Pce6BIoxTQ0AGCkxn/UBuzJFkYyJt71MadYQkjPqCQCJAFQ26sYh7MOKdU+VQFgPg== -"@next/swc-win32-arm64-msvc@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz#fb812cc4ca0042868e32a6a021da91943bb08b98" - integrity sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g== +"@next/swc-win32-arm64-msvc@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.21.tgz#290012ee57b196d3d2d04853e6bf0179cae9fbaf" + integrity sha512-plykgB3vL2hB4Z32W3ktsfqyuyGAPxqwiyrAi2Mr8LlEUhNn9VgkiAl5hODSBpzIfWweX3er1f5uNpGDygfQVQ== -"@next/swc-win32-ia32-msvc@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz#ec26e6169354f8ced240c1427be7fd485c5df898" - integrity sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ== +"@next/swc-win32-ia32-msvc@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.21.tgz#c959135a78cab18cca588d11d1e33bcf199590d4" + integrity sha512-w5bacz4Vxqrh06BjWgua3Yf7EMDb8iMcVhNrNx8KnJXt8t+Uu0Zg4JHLDL/T7DkTCEEfKXO/Er1fcfWxn2xfPA== -"@next/swc-win32-x64-msvc@14.2.15": - version "14.2.15" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz#18d68697002b282006771f8d92d79ade9efd35c4" - integrity sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g== +"@next/swc-win32-x64-msvc@14.2.21": + version "14.2.21" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.21.tgz#21ff892286555b90538a7d1b505ea21a005d6ead" + integrity sha512-sT6+llIkzpsexGYZq8cjjthRyRGe5cJVhqh12FmlbxHqna6zsDDK8UNaV7g41T6atFHCJUPeLb3uyAwrBwy0NA== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -3821,10 +3821,10 @@ jsonfile@^6.0.1: object.assign "^4.1.4" object.values "^1.1.6" -katex@^0.16.10: - version "0.16.17" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.17.tgz#72c588a0beca0cac10c30f447c2fb14647f773ed" - integrity sha512-OyzSrXBllz+Jdc9Auiw0kt21gbZ4hkz8Q5srVAb2U9INcYIfGKbxe+bvNvEz1bQ/NrDeRRho5eLCyk/L03maAw== +katex@^0.16.21: + version "0.16.21" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.21.tgz#8f63c659e931b210139691f2cc7bb35166b792a3" + integrity sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A== dependencies: commander "^8.3.0" @@ -4191,12 +4191,12 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@14.2.15: - version "14.2.15" - resolved "https://registry.yarnpkg.com/next/-/next-14.2.15.tgz#348e5603e22649775d19c785c09a89c9acb5189a" - integrity sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw== +next@14.2.21: + version "14.2.21" + resolved "https://registry.yarnpkg.com/next/-/next-14.2.21.tgz#f6da9e2abba1a0e4ca7a5273825daf06632554ba" + integrity sha512-rZmLwucLHr3/zfDMYbJXbw0ZeoBpirxkXuvsJbk7UPorvPYZhP7vq7aHbKnU7dQNCYIimRrbB2pp3xmf+wsYUg== dependencies: - "@next/env" "14.2.15" + "@next/env" "14.2.21" "@swc/helpers" "0.5.5" busboy "1.6.0" caniuse-lite "^1.0.30001579" @@ -4204,15 +4204,15 @@ next@14.2.15: postcss "8.4.31" styled-jsx "5.1.1" optionalDependencies: - "@next/swc-darwin-arm64" "14.2.15" - "@next/swc-darwin-x64" "14.2.15" - "@next/swc-linux-arm64-gnu" "14.2.15" - "@next/swc-linux-arm64-musl" "14.2.15" - "@next/swc-linux-x64-gnu" "14.2.15" - "@next/swc-linux-x64-musl" "14.2.15" - "@next/swc-win32-arm64-msvc" "14.2.15" - "@next/swc-win32-ia32-msvc" "14.2.15" - "@next/swc-win32-x64-msvc" "14.2.15" + "@next/swc-darwin-arm64" "14.2.21" + "@next/swc-darwin-x64" "14.2.21" + "@next/swc-linux-arm64-gnu" "14.2.21" + "@next/swc-linux-arm64-musl" "14.2.21" + "@next/swc-linux-x64-gnu" "14.2.21" + "@next/swc-linux-x64-musl" "14.2.21" + "@next/swc-win32-arm64-msvc" "14.2.21" + "@next/swc-win32-ia32-msvc" "14.2.21" + "@next/swc-win32-x64-msvc" "14.2.21" node-domexception@^1.0.0: version "1.0.0" From 82ff74cfa9a86e1955be6eeabe5a013cda3207bd Mon Sep 17 00:00:00 2001 From: sabaimran Date: Sun, 19 Jan 2025 23:57:57 -0800 Subject: [PATCH 29/33] Run on container with ubuntu latest for pytest gh action workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c68dbf96..480c9fa6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: test: name: Run Tests runs-on: ubuntu-latest - container: ubuntu:jammy + container: ubuntu:latest strategy: fail-fast: false matrix: From a214bd4100ed018929560e9735873ecdb61e5859 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Mon, 20 Jan 2025 00:05:35 -0800 Subject: [PATCH 30/33] upgrade pg server dev version to 15 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 480c9fa6..160b11d5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,7 +67,7 @@ jobs: env: DEBIAN_FRONTEND: noninteractive run : | - apt install -y postgresql postgresql-client && apt install -y postgresql-server-dev-14 + apt install -y postgresql postgresql-client && apt install -y postgresql-server-dev-15 - name: ⬇️ Install pip run: | From 95ad1f936eedb7bd16ced4a9f7bfe18d2e666951 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Mon, 20 Jan 2025 00:10:20 -0800 Subject: [PATCH 31/33] upgrade postgres server to 17 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 160b11d5..7a0251a4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,7 +67,7 @@ jobs: env: DEBIAN_FRONTEND: noninteractive run : | - apt install -y postgresql postgresql-client && apt install -y postgresql-server-dev-15 + apt install -y postgresql postgresql-client && apt install -y postgresql-server-dev-17 - name: ⬇️ Install pip run: | From bf58d9430b130451b0aff86aa29a6f50df7dad9a Mon Sep 17 00:00:00 2001 From: sabaimran Date: Mon, 20 Jan 2025 00:15:56 -0800 Subject: [PATCH 32/33] downgrade postgres server pkg to 16 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7a0251a4..93e4ae5e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,7 +67,7 @@ jobs: env: DEBIAN_FRONTEND: noninteractive run : | - apt install -y postgresql postgresql-client && apt install -y postgresql-server-dev-17 + apt install -y postgresql postgresql-client && apt install -y postgresql-server-dev-16 - name: ⬇️ Install pip run: | From 8fe08eecce42465fbb4f3164072dbf17b645f34c Mon Sep 17 00:00:00 2001 From: sabaimran Date: Mon, 20 Jan 2025 00:21:27 -0800 Subject: [PATCH 33/33] add --break-system-packages to bypass venv requirement --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 93e4ae5e..2c6f087c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,7 +79,7 @@ jobs: env: PIP_EXTRA_INDEX_URL: "https://download.pytorch.org/whl/cpu https://abetlen.github.io/llama-cpp-python/whl/cpu" CUDA_VISIBLE_DEVICES: "" - run: sed -i 's/dynamic = \["version"\]/version = "0.0.0"/' pyproject.toml && pip install --upgrade .[dev] + run: sed -i 's/dynamic = \["version"\]/version = "0.0.0"/' pyproject.toml && pip install --break-system-packages --upgrade .[dev] - name: 🧪 Test Application env: