mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-06 13:22:12 +00:00
Resolve merge conflicts with intro message in chat.html web view
This commit is contained in:
55
.github/workflows/dockerize.yml
vendored
55
.github/workflows/dockerize.yml
vendored
@@ -8,23 +8,47 @@ on:
|
|||||||
- master
|
- master
|
||||||
paths:
|
paths:
|
||||||
- src/khoj/**
|
- src/khoj/**
|
||||||
- config/**
|
|
||||||
- pyproject.toml
|
- pyproject.toml
|
||||||
- Dockerfile
|
- Dockerfile
|
||||||
|
- prod.Dockerfile
|
||||||
- docker-compose.yml
|
- docker-compose.yml
|
||||||
- .github/workflows/dockerize.yml
|
- .github/workflows/dockerize.yml
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: 'Docker image tag'
|
||||||
|
default: 'dev'
|
||||||
|
khoj:
|
||||||
|
description: 'Build Khoj docker image'
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
khoj-cloud:
|
||||||
|
description: 'Build Khoj cloud docker image'
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DOCKER_IMAGE_TAG: ${{ github.ref == 'refs/heads/master' && 'latest' || github.ref_name }}
|
# Tag Image with tag name on release
|
||||||
|
# else with user specified tag (default 'dev') if triggered via workflow
|
||||||
|
# else with 'pre' (if push to master)
|
||||||
|
DOCKER_IMAGE_TAG: ${{ github.ref_type == 'tag' && github.ref_name || github.event_name == 'workflow_dispatch' && github.event.inputs.tag || 'pre' }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build Docker Image, Push to Container Registry
|
name: Publish Khoj Docker Images
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
image:
|
||||||
|
- 'local'
|
||||||
|
- 'cloud'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
# Get all history to correctly infer Khoj version using hatch
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
@@ -36,13 +60,36 @@ jobs:
|
|||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.PAT }}
|
password: ${{ secrets.PAT }}
|
||||||
|
|
||||||
|
- name: Get App Version
|
||||||
|
id: hatch
|
||||||
|
run: echo "version=$(pipx run hatch version)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: 📦 Build and Push Docker Image
|
- name: 📦 Build and Push Docker Image
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
|
if: (matrix.image == 'local' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj == 'true' || (matrix.image == 'local' && github.event_name == 'push')
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: Dockerfile
|
file: Dockerfile
|
||||||
platforms: linux/amd64, linux/arm64
|
platforms: linux/amd64, linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }}
|
tags: |
|
||||||
|
ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }}
|
||||||
|
${{ github.ref_type == 'tag' && format('ghcr.io/{0}:latest', github.repository) || '' }}
|
||||||
build-args: |
|
build-args: |
|
||||||
|
VERSION=${{ steps.hatch.outputs.version }}
|
||||||
|
PORT=42110
|
||||||
|
|
||||||
|
- name: 📦️⛅️ Build and Push Cloud Docker Image
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
if: (matrix.image == 'cloud' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj-cloud == 'true' || (matrix.image == 'cloud' && github.event_name == 'push')
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: prod.Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }}
|
||||||
|
${{ github.ref_type == 'tag' && format('ghcr.io/{0}-cloud:latest', github.repository) || '' }}
|
||||||
|
build-args: |
|
||||||
|
VERSION=${{ steps.hatch.outputs.version }}
|
||||||
PORT=42110
|
PORT=42110
|
||||||
|
|||||||
52
.github/workflows/dockerize_production.yml
vendored
52
.github/workflows/dockerize_production.yml
vendored
@@ -1,52 +0,0 @@
|
|||||||
name: dockerize production
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- src/khoj/**
|
|
||||||
- pyproject.toml
|
|
||||||
- prod.Dockerfile
|
|
||||||
- .github/workflows/dockerize_production.yml
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "*"
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths:
|
|
||||||
- src/khoj/**
|
|
||||||
- pyproject.toml
|
|
||||||
- prod.Dockerfile
|
|
||||||
- .github/workflows/dockerize_production.yml
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
DOCKER_IMAGE_TAG: ${{ github.event_name == 'pull_request' && 'dev' || (github.ref == 'refs/heads/master' && 'latest' || github.ref_name) }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build Production Docker Image, Push to Container Registry
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.PAT }}
|
|
||||||
|
|
||||||
- name: 📦 Build and Push Docker Image
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: prod.Dockerfile
|
|
||||||
platforms: linux/amd64
|
|
||||||
push: true
|
|
||||||
tags: ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }}
|
|
||||||
build-args: |
|
|
||||||
PORT=42110
|
|
||||||
@@ -10,7 +10,8 @@ WORKDIR /app
|
|||||||
# Install Application
|
# Install Application
|
||||||
COPY pyproject.toml .
|
COPY pyproject.toml .
|
||||||
COPY README.md .
|
COPY README.md .
|
||||||
RUN sed -i 's/dynamic = \["version"\]/version = "0.0.0"/' pyproject.toml && \
|
ARG VERSION=0.0.0
|
||||||
|
RUN sed -i "s/dynamic = \\[\"version\"\\]/version = \"$VERSION\"/" pyproject.toml && \
|
||||||
pip install --no-cache-dir .
|
pip install --no-cache-dir .
|
||||||
|
|
||||||
# Copy Source Code
|
# Copy Source Code
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
content-type:
|
|
||||||
# The /data/folder/ prefix to the folders is here because this is
|
|
||||||
# the directory to which the local files are copied in the docker-compose.
|
|
||||||
# If changing, the docker-compose volumes should also be changed to match.
|
|
||||||
org:
|
|
||||||
input-files: null
|
|
||||||
input-filter: ["/data/org/**/*.org"]
|
|
||||||
compressed-jsonl: "/data/embeddings/notes.jsonl.gz"
|
|
||||||
embeddings-file: "/data/embeddings/note_embeddings.pt"
|
|
||||||
index_heading_entries: false
|
|
||||||
|
|
||||||
markdown:
|
|
||||||
input-files: null
|
|
||||||
input-filter: ["/data/markdown/**/*.markdown"]
|
|
||||||
compressed-jsonl: "/data/embeddings/markdown.jsonl.gz"
|
|
||||||
embeddings-file: "/data/embeddings/markdown_embeddings.pt"
|
|
||||||
|
|
||||||
pdf:
|
|
||||||
input-files: null
|
|
||||||
input-filter: ["/data/pdf/**/*.pdf"]
|
|
||||||
compressed-jsonl: "/data/embeddings/pdf.jsonl.gz"
|
|
||||||
embeddings-file: "/data/embeddings/pdf_embeddings.pt"
|
|
||||||
|
|
||||||
image:
|
|
||||||
input-directories: ["/data/images/"]
|
|
||||||
embeddings-file: "/data/embeddings/image_embeddings.pt"
|
|
||||||
batch-size: 50
|
|
||||||
use-xmp-metadata: false
|
|
||||||
|
|
||||||
notion: null
|
|
||||||
github: null
|
|
||||||
plugins: null
|
|
||||||
|
|
||||||
search-type:
|
|
||||||
symmetric: null
|
|
||||||
asymmetric:
|
|
||||||
encoder: "sentence-transformers/multi-qa-MiniLM-L6-cos-v1"
|
|
||||||
cross-encoder: "cross-encoder/ms-marco-MiniLM-L-6-v2"
|
|
||||||
model_directory: "/data/models/asymmetric"
|
|
||||||
image:
|
|
||||||
encoder: "sentence-transformers/clip-ViT-B-32"
|
|
||||||
model_directory: "/data/models/image_encoder"
|
|
||||||
|
|
||||||
processor:
|
|
||||||
conversation:
|
|
||||||
conversation-logfile: "/data/embeddings/conversation_logs.json"
|
|
||||||
enable-offline-chat: false
|
|
||||||
openai: null
|
|
||||||
|
|
||||||
app:
|
|
||||||
should_log_telemetry: true
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
content-type:
|
|
||||||
org:
|
|
||||||
input-files: # ["/path/to/org-file.org"] REQUIRED IF input-filter IS NOT SET OR
|
|
||||||
input-filter: # ["/path/to/org/*.org"] REQUIRED IF input-files IS NOT SET
|
|
||||||
compressed-jsonl: "~/.khoj/content/org/org.jsonl.gz"
|
|
||||||
embeddings-file: "~/.khoj/content/org/org_embeddings.pt"
|
|
||||||
index_heading_entries: false # Set to true to index entries with empty body
|
|
||||||
|
|
||||||
markdown:
|
|
||||||
input-files: # ["/path/to/markdown-file.md"] REQUIRED IF input-filter IS NOT SET OR
|
|
||||||
input-filter: # ["/path/to/markdown/*.md"] REQUIRED IF input-files IS NOT SET
|
|
||||||
compressed-jsonl: "~/.khoj/content/markdown/markdown.jsonl.gz"
|
|
||||||
embeddings-file: "~/.khoj/content/markdown/markdown_embeddings.pt"
|
|
||||||
|
|
||||||
ledger:
|
|
||||||
input-files: # ["/path/to/ledger-file.beancount"] REQUIRED IF input-filter is not set OR
|
|
||||||
input-filter: # ["/path/to/ledger/*.beancount"] REQUIRED IF input-files is not set
|
|
||||||
compressed-jsonl: "~/.khoj/content/ledger/ledger.jsonl.gz"
|
|
||||||
embeddings-file: "~/.khoj/content/ledger/ledger_embeddings.pt"
|
|
||||||
|
|
||||||
image:
|
|
||||||
input-directories: # ["/path/to/images/"] REQUIRED IF input-filter IS NOT SET OR
|
|
||||||
input-filter: # ["/path/to/images/*.jpg"] REQUIRED IF input-directories IS NOT SET
|
|
||||||
embeddings-file: "~/.khoj/content/image/image_embeddings.pt"
|
|
||||||
batch-size: 50
|
|
||||||
use-xmp-metadata: false
|
|
||||||
|
|
||||||
music:
|
|
||||||
input-files: # ["/path/to/music-file.org"] REQUIRED IF input-filter IS NOT SET OR
|
|
||||||
input-filter: # ["/path/to/music/*.org"] REQUIRED IF input-files IS NOT SET
|
|
||||||
compressed-jsonl: "~/.khoj/content/music/music.jsonl.gz"
|
|
||||||
embeddings-file: "~/.khoj/content/music/music_embeddings.pt"
|
|
||||||
|
|
||||||
search-type:
|
|
||||||
symmetric:
|
|
||||||
encoder: "sentence-transformers/all-MiniLM-L6-v2"
|
|
||||||
cross-encoder: "cross-encoder/ms-marco-MiniLM-L-6-v2"
|
|
||||||
encoder-type: sentence_transformers.SentenceTransformer
|
|
||||||
model_directory: "~/.khoj/search/symmetric/"
|
|
||||||
|
|
||||||
asymmetric:
|
|
||||||
encoder: "sentence-transformers/multi-qa-MiniLM-L6-cos-v1"
|
|
||||||
cross-encoder: "cross-encoder/ms-marco-MiniLM-L-6-v2"
|
|
||||||
encoder-type: sentence_transformers.SentenceTransformer
|
|
||||||
model_directory: "~/.khoj/search/asymmetric/"
|
|
||||||
|
|
||||||
image:
|
|
||||||
encoder: "sentence-transformers/clip-ViT-B-32"
|
|
||||||
encoder-type: sentence_transformers.SentenceTransformer
|
|
||||||
model_directory: "~/.khoj/search/image/"
|
|
||||||
|
|
||||||
processor:
|
|
||||||
conversation:
|
|
||||||
openai-api-key: # "YOUR_OPENAI_API_KEY"
|
|
||||||
model: "text-davinci-003"
|
|
||||||
chat-model: "gpt-3.5-turbo"
|
|
||||||
conversation-logfile: "~/.khoj/processor/conversation/conversation_logs.json"
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "khoj",
|
"id": "khoj",
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "An AI copilot for your Second Brain",
|
"description": "An AI copilot for your Second Brain",
|
||||||
"author": "Khoj Inc.",
|
"author": "Khoj Inc.",
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ WORKDIR /app
|
|||||||
# Install Application
|
# Install Application
|
||||||
COPY pyproject.toml .
|
COPY pyproject.toml .
|
||||||
COPY README.md .
|
COPY README.md .
|
||||||
RUN sed -i 's/dynamic = \["version"\]/version = "0.0.0"/' pyproject.toml && \
|
ARG VERSION=0.0.0
|
||||||
|
RUN sed -i "s/dynamic = \\[\"version\"\\]/version = \"$VERSION\"/" pyproject.toml && \
|
||||||
TMPDIR=/home/cache/ pip install --cache-dir=/home/cache/ -e .
|
TMPDIR=/home/cache/ pip install --cache-dir=/home/cache/ -e .
|
||||||
|
|
||||||
# Copy Source Code
|
# Copy Source Code
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ do
|
|||||||
# Bump Desktop app to current version
|
# Bump Desktop app to current version
|
||||||
cd $project_root/src/interface/desktop
|
cd $project_root/src/interface/desktop
|
||||||
sed -E -i.bak "s/version\": \"(.*)\",/version\": \"$current_version\",/" package.json
|
sed -E -i.bak "s/version\": \"(.*)\",/version\": \"$current_version\",/" package.json
|
||||||
|
rm *.bak
|
||||||
|
|
||||||
# Bump Obsidian plugin to current version
|
# Bump Obsidian plugin to current version
|
||||||
cd $project_root/src/interface/obsidian
|
cd $project_root/src/interface/obsidian
|
||||||
@@ -37,6 +38,7 @@ do
|
|||||||
|
|
||||||
# Commit changes and tag commit for release
|
# Commit changes and tag commit for release
|
||||||
git add \
|
git add \
|
||||||
|
$project_root/src/interface/desktop/package.json \
|
||||||
$project_root/src/interface/obsidian/package.json \
|
$project_root/src/interface/obsidian/package.json \
|
||||||
$project_root/src/interface/obsidian/manifest.json \
|
$project_root/src/interface/obsidian/manifest.json \
|
||||||
$project_root/src/interface/obsidian/versions.json \
|
$project_root/src/interface/obsidian/versions.json \
|
||||||
@@ -52,6 +54,11 @@ do
|
|||||||
next_version=$(touch bump.txt && git add bump.txt && hatch version | sed 's/\.dev.*//g')
|
next_version=$(touch bump.txt && git add bump.txt && hatch version | sed 's/\.dev.*//g')
|
||||||
git rm --cached -- bump.txt && rm bump.txt
|
git rm --cached -- bump.txt && rm bump.txt
|
||||||
|
|
||||||
|
# Bump Desktop app to next version
|
||||||
|
cd $project_root/src/interface/desktop
|
||||||
|
sed -E -i.bak "s/version\": \"(.*)\",/version\": \"$current_version\",/" package.json
|
||||||
|
rm *.bak
|
||||||
|
|
||||||
# Bump Obsidian plugins to next version
|
# Bump Obsidian plugins to next version
|
||||||
cd $project_root/src/interface/obsidian
|
cd $project_root/src/interface/obsidian
|
||||||
sed -E -i.bak "s/version\": \"(.*)\",/version\": \"$next_version\",/" package.json
|
sed -E -i.bak "s/version\": \"(.*)\",/version\": \"$next_version\",/" package.json
|
||||||
@@ -69,6 +76,7 @@ do
|
|||||||
|
|
||||||
# Commit changes
|
# Commit changes
|
||||||
git add \
|
git add \
|
||||||
|
$project_root/src/interface/desktop/package.json \
|
||||||
$project_root/src/interface/obsidian/package.json \
|
$project_root/src/interface/obsidian/package.json \
|
||||||
$project_root/src/interface/obsidian/manifest.json \
|
$project_root/src/interface/obsidian/manifest.json \
|
||||||
$project_root/src/interface/obsidian/versions.json \
|
$project_root/src/interface/obsidian/versions.json \
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
let short_ref = escaped_ref.slice(0, 100);
|
let short_ref = escaped_ref.slice(0, 100);
|
||||||
short_ref = short_ref.length < escaped_ref.length ? short_ref + "..." : short_ref;
|
short_ref = short_ref.length < escaped_ref.length ? short_ref + "..." : short_ref;
|
||||||
let referenceButton = document.createElement('button');
|
let referenceButton = document.createElement('button');
|
||||||
referenceButton.innerHTML = short_ref;
|
referenceButton.textContent = short_ref;
|
||||||
referenceButton.id = `ref-${index}`;
|
referenceButton.id = `ref-${index}`;
|
||||||
referenceButton.classList.add("reference-button");
|
referenceButton.classList.add("reference-button");
|
||||||
referenceButton.classList.add("collapsed");
|
referenceButton.classList.add("collapsed");
|
||||||
@@ -58,11 +58,11 @@
|
|||||||
if (this.classList.contains("collapsed")) {
|
if (this.classList.contains("collapsed")) {
|
||||||
this.classList.remove("collapsed");
|
this.classList.remove("collapsed");
|
||||||
this.classList.add("expanded");
|
this.classList.add("expanded");
|
||||||
this.innerHTML = escaped_ref;
|
this.textContent = escaped_ref;
|
||||||
} else {
|
} else {
|
||||||
this.classList.add("collapsed");
|
this.classList.add("collapsed");
|
||||||
this.classList.remove("expanded");
|
this.classList.remove("expanded");
|
||||||
this.innerHTML = short_ref;
|
this.textContent = short_ref;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -115,10 +115,10 @@
|
|||||||
return referenceButton;
|
return referenceButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMessage(message, by, dt=null, annotations=null) {
|
function renderMessage(message, by, dt=null, annotations=null, raw=false) {
|
||||||
let message_time = formatDate(dt ?? new Date());
|
let message_time = formatDate(dt ?? new Date());
|
||||||
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
||||||
let formattedMessage = formatHTMLMessage(message);
|
let formattedMessage = formatHTMLMessage(message, raw);
|
||||||
let chatBody = document.getElementById("chat-body");
|
let chatBody = document.getElementById("chat-body");
|
||||||
|
|
||||||
// Create a new div for the chat message
|
// Create a new div for the chat message
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
renderMessage(message, by, dt, references);
|
renderMessage(message, by, dt, references);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatHTMLMessage(htmlMessage) {
|
function formatHTMLMessage(htmlMessage, raw=false) {
|
||||||
var md = window.markdownit();
|
var md = window.markdownit();
|
||||||
let newHTML = htmlMessage;
|
let newHTML = htmlMessage;
|
||||||
|
|
||||||
@@ -267,7 +267,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Render markdown
|
// Render markdown
|
||||||
newHTML = md.render(newHTML);
|
newHTML = raw ? newHTML : md.render(newHTML);
|
||||||
// Get any elements with a class that starts with "language"
|
// Get any elements with a class that starts with "language"
|
||||||
let element = document.createElement('div');
|
let element = document.createElement('div');
|
||||||
element.innerHTML = newHTML;
|
element.innerHTML = newHTML;
|
||||||
@@ -574,7 +574,7 @@
|
|||||||
.trim()
|
.trim()
|
||||||
.replace(/(\r\n|\n|\r)/gm, "");
|
.replace(/(\r\n|\n|\r)/gm, "");
|
||||||
|
|
||||||
renderMessage(first_run_message, "khoj");
|
renderMessage(first_run_message, "khoj", null, null, true);
|
||||||
|
|
||||||
// Disable chat input field and update placeholder text
|
// Disable chat input field and update placeholder text
|
||||||
document.getElementById("chat-input").setAttribute("disabled", "disabled");
|
document.getElementById("chat-input").setAttribute("disabled", "disabled");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"description": "An AI copilot for your Second Brain",
|
"description": "An AI copilot for your Second Brain",
|
||||||
"author": "Saba Imran, Debanjum Singh Solanky <team@khoj.dev>",
|
"author": "Saba Imran, Debanjum Singh Solanky <team@khoj.dev>",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
;; Saba Imran <saba@khoj.dev>
|
;; Saba Imran <saba@khoj.dev>
|
||||||
;; Description: An AI copilot for your Second Brain
|
;; Description: An AI copilot for your Second Brain
|
||||||
;; Keywords: search, chat, org-mode, outlines, markdown, pdf, image
|
;; Keywords: search, chat, org-mode, outlines, markdown, pdf, image
|
||||||
;; Version: 1.1.0
|
;; Version: 1.2.0
|
||||||
;; Package-Requires: ((emacs "27.1") (transient "0.3.0") (dash "2.19.1"))
|
;; 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
|
;; URL: https://github.com/khoj-ai/khoj/tree/master/src/interface/emacs
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "khoj",
|
"id": "khoj",
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "An AI copilot for your Second Brain",
|
"description": "An AI copilot for your Second Brain",
|
||||||
"author": "Khoj Inc.",
|
"author": "Khoj Inc.",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"description": "An AI copilot for your Second Brain",
|
"description": "An AI copilot for your Second Brain",
|
||||||
"author": "Debanjum Singh Solanky, Saba Imran <team@khoj.dev>",
|
"author": "Debanjum Singh Solanky, Saba Imran <team@khoj.dev>",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
|
|||||||
@@ -41,20 +41,21 @@ export class KhojChatModal extends Modal {
|
|||||||
let chatBodyEl = contentEl.createDiv({ attr: { id: "khoj-chat-body", class: "khoj-chat-body" } });
|
let chatBodyEl = contentEl.createDiv({ attr: { id: "khoj-chat-body", class: "khoj-chat-body" } });
|
||||||
|
|
||||||
// Get chat history from Khoj backend
|
// Get chat history from Khoj backend
|
||||||
await this.getChatHistory(chatBodyEl);
|
let getChatHistorySucessfully = await this.getChatHistory(chatBodyEl);
|
||||||
|
let placeholderText = getChatHistorySucessfully ? "Chat with Khoj [Hit Enter to send message]" : "Configure Khoj to enable chat";
|
||||||
|
|
||||||
// Add chat input field
|
// Add chat input field
|
||||||
let inputRow = contentEl.createDiv("khoj-input-row");
|
let inputRow = contentEl.createDiv("khoj-input-row");
|
||||||
const chatInput = inputRow.createEl("input",
|
let chatInput = inputRow.createEl("input", {
|
||||||
{
|
attr: {
|
||||||
attr: {
|
type: "text",
|
||||||
type: "text",
|
id: "khoj-chat-input",
|
||||||
id: "khoj-chat-input",
|
autofocus: "autofocus",
|
||||||
autofocus: "autofocus",
|
placeholder: placeholderText,
|
||||||
placeholder: "Chat with Khoj [Hit Enter to send message]",
|
class: "khoj-chat-input option",
|
||||||
class: "khoj-chat-input option"
|
disabled: !getChatHistorySucessfully ? "disabled" : null
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
let transcribe = inputRow.createEl("button", {
|
let transcribe = inputRow.createEl("button", {
|
||||||
text: "Transcribe",
|
text: "Transcribe",
|
||||||
@@ -88,7 +89,7 @@ export class KhojChatModal extends Modal {
|
|||||||
let short_ref = escaped_ref.slice(0, 100);
|
let short_ref = escaped_ref.slice(0, 100);
|
||||||
short_ref = short_ref.length < escaped_ref.length ? short_ref + "..." : short_ref;
|
short_ref = short_ref.length < escaped_ref.length ? short_ref + "..." : short_ref;
|
||||||
let referenceButton = messageEl.createEl('button');
|
let referenceButton = messageEl.createEl('button');
|
||||||
referenceButton.innerHTML = short_ref;
|
referenceButton.textContent = short_ref;
|
||||||
referenceButton.id = `ref-${index}`;
|
referenceButton.id = `ref-${index}`;
|
||||||
referenceButton.classList.add("reference-button");
|
referenceButton.classList.add("reference-button");
|
||||||
referenceButton.classList.add("collapsed");
|
referenceButton.classList.add("collapsed");
|
||||||
@@ -100,11 +101,11 @@ export class KhojChatModal extends Modal {
|
|||||||
if (this.classList.contains("collapsed")) {
|
if (this.classList.contains("collapsed")) {
|
||||||
this.classList.remove("collapsed");
|
this.classList.remove("collapsed");
|
||||||
this.classList.add("expanded");
|
this.classList.add("expanded");
|
||||||
this.innerHTML = escaped_ref;
|
this.textContent = escaped_ref;
|
||||||
} else {
|
} else {
|
||||||
this.classList.add("collapsed");
|
this.classList.add("collapsed");
|
||||||
this.classList.remove("expanded");
|
this.classList.remove("expanded");
|
||||||
this.innerHTML = short_ref;
|
this.textContent = short_ref;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ export class KhojChatModal extends Modal {
|
|||||||
referenceExpandButton.innerHTML = expandButtonText;
|
referenceExpandButton.innerHTML = expandButtonText;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessage(chatEl: Element, message: string, sender: string, dt?: Date): Element {
|
renderMessage(chatEl: Element, message: string, sender: string, dt?: Date, raw: boolean=false): Element {
|
||||||
let message_time = this.formatDate(dt ?? new Date());
|
let message_time = this.formatDate(dt ?? new Date());
|
||||||
let emojified_sender = sender == "khoj" ? "🏮 Khoj" : "🤔 You";
|
let emojified_sender = sender == "khoj" ? "🏮 Khoj" : "🤔 You";
|
||||||
|
|
||||||
@@ -177,8 +178,12 @@ export class KhojChatModal extends Modal {
|
|||||||
let chat_message_body_el = chatMessageEl.createDiv();
|
let chat_message_body_el = chatMessageEl.createDiv();
|
||||||
chat_message_body_el.addClasses(["khoj-chat-message-text", sender]);
|
chat_message_body_el.addClasses(["khoj-chat-message-text", sender]);
|
||||||
let chat_message_body_text_el = chat_message_body_el.createDiv();
|
let chat_message_body_text_el = chat_message_body_el.createDiv();
|
||||||
// @ts-ignore
|
if (raw) {
|
||||||
MarkdownRenderer.renderMarkdown(message, chat_message_body_text_el, null, null);
|
chat_message_body_text_el.innerHTML = message;
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
MarkdownRenderer.renderMarkdown(message, chat_message_body_text_el, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove user-select: none property to make text selectable
|
// Remove user-select: none property to make text selectable
|
||||||
chatMessageEl.style.userSelect = "text";
|
chatMessageEl.style.userSelect = "text";
|
||||||
@@ -212,11 +217,11 @@ export class KhojChatModal extends Modal {
|
|||||||
return chat_message_el
|
return chat_message_el
|
||||||
}
|
}
|
||||||
|
|
||||||
renderIncrementalMessage(htmlElement: HTMLDivElement, additionalMessage: string) {
|
async renderIncrementalMessage(htmlElement: HTMLDivElement, additionalMessage: string) {
|
||||||
this.result += additionalMessage;
|
this.result += additionalMessage;
|
||||||
htmlElement.innerHTML = "";
|
htmlElement.innerHTML = "";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
MarkdownRenderer.renderMarkdown(this.result, htmlElement, null, null);
|
await MarkdownRenderer.renderMarkdown(this.result, htmlElement, null, null);
|
||||||
// Scroll to bottom of modal, till the send message input box
|
// Scroll to bottom of modal, till the send message input box
|
||||||
this.modalEl.scrollTop = this.modalEl.scrollHeight;
|
this.modalEl.scrollTop = this.modalEl.scrollHeight;
|
||||||
}
|
}
|
||||||
@@ -228,15 +233,33 @@ export class KhojChatModal extends Modal {
|
|||||||
return `${time_string}, ${date_string}`;
|
return `${time_string}, ${date_string}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChatHistory(chatBodyEl: Element): Promise<void> {
|
async getChatHistory(chatBodyEl: Element): Promise<boolean> {
|
||||||
// Get chat history from Khoj backend
|
// Get chat history from Khoj backend
|
||||||
let chatUrl = `${this.setting.khojUrl}/api/chat/history?client=obsidian`;
|
let chatUrl = `${this.setting.khojUrl}/api/chat/history?client=obsidian`;
|
||||||
let headers = { "Authorization": `Bearer ${this.setting.khojApiKey}` };
|
let headers = { "Authorization": `Bearer ${this.setting.khojApiKey}` };
|
||||||
let response = await request({ url: chatUrl, headers: headers });
|
|
||||||
let chatLogs = JSON.parse(response).response;
|
try {
|
||||||
chatLogs.forEach((chatLog: any) => {
|
let response = await fetch(chatUrl, { method: "GET", headers: headers });
|
||||||
this.renderMessageWithReferences(chatBodyEl, chatLog.message, chatLog.by, chatLog.context, new Date(chatLog.created), chatLog.intent?.type);
|
let responseJson: any = await response.json();
|
||||||
});
|
|
||||||
|
if (responseJson.detail) {
|
||||||
|
// If the server returns error details in response, render a setup hint.
|
||||||
|
let setupMsg = "Hi 👋🏾, to start chatting add available chat models options via [the Django Admin panel](/server/admin) on the Server";
|
||||||
|
this.renderMessage(chatBodyEl, setupMsg, "khoj", undefined, true);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (responseJson.response) {
|
||||||
|
let chatLogs = responseJson.response;
|
||||||
|
chatLogs.forEach((chatLog: any) => {
|
||||||
|
this.renderMessageWithReferences(chatBodyEl, chatLog.message, chatLog.by, chatLog.context, new Date(chatLog.created), chatLog.intent?.type);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
let errorMsg = "Unable to get response from Khoj server ❤️🩹. Ensure server is running or contact developers for help at [team@khoj.dev](mailto:team@khoj.dev) or in [Discord](https://discord.gg/BDgyabRM6e)";
|
||||||
|
this.renderMessage(chatBodyEl, errorMsg, "khoj", undefined);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChatResponse(query: string | undefined | null): Promise<void> {
|
async getChatResponse(query: string | undefined | null): Promise<void> {
|
||||||
@@ -254,7 +277,7 @@ export class KhojChatModal extends Modal {
|
|||||||
|
|
||||||
// Temporary status message to indicate that Khoj is thinking
|
// Temporary status message to indicate that Khoj is thinking
|
||||||
this.result = "";
|
this.result = "";
|
||||||
this.renderIncrementalMessage(responseElement, "🤔");
|
await this.renderIncrementalMessage(responseElement, "🤔");
|
||||||
|
|
||||||
let response = await fetch(chatUrl, {
|
let response = await fetch(chatUrl, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -289,17 +312,16 @@ export class KhojChatModal extends Modal {
|
|||||||
// If the chunk is not a JSON object, just display it as is
|
// If the chunk is not a JSON object, just display it as is
|
||||||
responseText = response.body.read().toString()
|
responseText = response.body.read().toString()
|
||||||
} finally {
|
} finally {
|
||||||
this.renderIncrementalMessage(responseElement, responseText);
|
await this.renderIncrementalMessage(responseElement, responseText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for await (const chunk of response.body) {
|
for await (const chunk of response.body) {
|
||||||
let responseText = chunk.toString();
|
let responseText = chunk.toString();
|
||||||
if (responseText.includes("### compiled references:")) {
|
if (responseText.includes("### compiled references:")) {
|
||||||
const additionalResponse = responseText.split("### compiled references:")[0];
|
const [additionalResponse, rawReference] = responseText.split("### compiled references:", 2);
|
||||||
this.renderIncrementalMessage(responseElement, additionalResponse);
|
await this.renderIncrementalMessage(responseElement, additionalResponse);
|
||||||
|
|
||||||
const rawReference = responseText.split("### compiled references:")[1];
|
|
||||||
const rawReferenceAsJson = JSON.parse(rawReference);
|
const rawReferenceAsJson = JSON.parse(rawReference);
|
||||||
let references = responseElement.createDiv();
|
let references = responseElement.createDiv();
|
||||||
references.classList.add("references");
|
references.classList.add("references");
|
||||||
@@ -337,17 +359,12 @@ export class KhojChatModal extends Modal {
|
|||||||
referenceExpandButton.innerHTML = expandButtonText;
|
referenceExpandButton.innerHTML = expandButtonText;
|
||||||
references.appendChild(referenceSection);
|
references.appendChild(referenceSection);
|
||||||
} else {
|
} else {
|
||||||
if (responseText.startsWith("{") && responseText.endsWith("}")) {
|
await this.renderIncrementalMessage(responseElement, responseText);
|
||||||
} else {
|
|
||||||
// If the chunk is not a JSON object, just display it as is
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.renderIncrementalMessage(responseElement, responseText);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.renderIncrementalMessage(responseElement, "Sorry, unable to get response from Khoj backend ❤️🩹. Contact developer for help at team@khoj.dev or <a href='https://discord.gg/BDgyabRM6e'>in Discord</a>")
|
let errorMsg = "Sorry, unable to get response from Khoj backend ❤️🩹. Contact developer for help at team@khoj.dev or [in Discord](https://discord.gg/BDgyabRM6e)";
|
||||||
|
responseElement.innerHTML = errorMsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,10 +394,11 @@ export class KhojChatModal extends Modal {
|
|||||||
// Throw error if conversation history isn't cleared
|
// Throw error if conversation history isn't cleared
|
||||||
throw new Error("Failed to clear conversation history");
|
throw new Error("Failed to clear conversation history");
|
||||||
} else {
|
} else {
|
||||||
|
let getChatHistoryStatus = await this.getChatHistory(chatBody);
|
||||||
// If conversation history is cleared successfully, clear chat logs from modal
|
// If conversation history is cleared successfully, clear chat logs from modal
|
||||||
chatBody.innerHTML = "";
|
if (getChatHistoryStatus) chatBody.innerHTML = "";
|
||||||
await this.getChatHistory(chatBody);
|
let statusMsg = getChatHistoryStatus ? result.message : "Failed to clear conversation history";
|
||||||
this.flashStatusInChatInput(result.message);
|
this.flashStatusInChatInput(statusMsg);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.flashStatusInChatInput("Failed to clear conversation history");
|
this.flashStatusInChatInput("Failed to clear conversation history");
|
||||||
|
|||||||
@@ -29,5 +29,6 @@
|
|||||||
"0.14.0": "0.15.0",
|
"0.14.0": "0.15.0",
|
||||||
"1.0.0": "0.15.0",
|
"1.0.0": "0.15.0",
|
||||||
"1.0.1": "0.15.0",
|
"1.0.1": "0.15.0",
|
||||||
"1.1.0": "0.15.0"
|
"1.1.0": "0.15.0",
|
||||||
|
"1.2.0": "0.15.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Hi, I am Khoj, your open, personal AI 👋🏽. I can help:
|
|||||||
- 🔎 Search the web for answers to your questions
|
- 🔎 Search the web for answers to your questions
|
||||||
- 🎙️ Listen to your audio messages
|
- 🎙️ Listen to your audio messages
|
||||||
|
|
||||||
Download the [🖥️ Desktop app](https://khoj.dev/downloads) to share your documents with me.
|
Get the Khoj [Desktop](https://khoj.dev/downloads), [Obsidian](https://docs.khoj.dev/#/obsidian?id=setup) or [Emacs](https://docs.khoj.dev/#/emacs?id=setup) app to search, chat with your 🖥️ computer docs.
|
||||||
|
|
||||||
To get started, just start typing below. You can also type / to see a list of commands.
|
To get started, just start typing below. You can also type / to see a list of commands.
|
||||||
`.trim()
|
`.trim()
|
||||||
@@ -58,7 +58,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
let short_ref = escaped_ref.slice(0, 140);
|
let short_ref = escaped_ref.slice(0, 140);
|
||||||
short_ref = short_ref.length < escaped_ref.length ? short_ref + "..." : short_ref;
|
short_ref = short_ref.length < escaped_ref.length ? short_ref + "..." : short_ref;
|
||||||
let referenceButton = document.createElement('button');
|
let referenceButton = document.createElement('button');
|
||||||
referenceButton.innerHTML = short_ref;
|
referenceButton.textContent = short_ref;
|
||||||
referenceButton.id = `ref-${index}`;
|
referenceButton.id = `ref-${index}`;
|
||||||
referenceButton.classList.add("reference-button");
|
referenceButton.classList.add("reference-button");
|
||||||
referenceButton.classList.add("collapsed");
|
referenceButton.classList.add("collapsed");
|
||||||
@@ -70,11 +70,11 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
if (this.classList.contains("collapsed")) {
|
if (this.classList.contains("collapsed")) {
|
||||||
this.classList.remove("collapsed");
|
this.classList.remove("collapsed");
|
||||||
this.classList.add("expanded");
|
this.classList.add("expanded");
|
||||||
this.innerHTML = escaped_ref;
|
this.textContent = escaped_ref;
|
||||||
} else {
|
} else {
|
||||||
this.classList.add("collapsed");
|
this.classList.add("collapsed");
|
||||||
this.classList.remove("expanded");
|
this.classList.remove("expanded");
|
||||||
this.innerHTML = short_ref;
|
this.textContent = short_ref;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -127,10 +127,10 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
return referenceButton;
|
return referenceButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMessage(message, by, dt=null, annotations=null) {
|
function renderMessage(message, by, dt=null, annotations=null, raw=false) {
|
||||||
let message_time = formatDate(dt ?? new Date());
|
let message_time = formatDate(dt ?? new Date());
|
||||||
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
||||||
let formattedMessage = formatHTMLMessage(message);
|
let formattedMessage = formatHTMLMessage(message, raw);
|
||||||
let chatBody = document.getElementById("chat-body");
|
let chatBody = document.getElementById("chat-body");
|
||||||
|
|
||||||
// Create a new div for the chat message
|
// Create a new div for the chat message
|
||||||
@@ -260,7 +260,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
renderMessage(message, by, dt, references);
|
renderMessage(message, by, dt, references);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatHTMLMessage(htmlMessage) {
|
function formatHTMLMessage(htmlMessage, raw=false) {
|
||||||
var md = window.markdownit();
|
var md = window.markdownit();
|
||||||
let newHTML = htmlMessage;
|
let newHTML = htmlMessage;
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Render markdown
|
// Render markdown
|
||||||
newHTML = md.render(newHTML);
|
newHTML = raw ? newHTML : md.render(newHTML);
|
||||||
// Get any elements with a class that starts with "language"
|
// Get any elements with a class that starts with "language"
|
||||||
let element = document.createElement('div');
|
let element = document.createElement('div');
|
||||||
element.innerHTML = newHTML;
|
element.innerHTML = newHTML;
|
||||||
@@ -438,9 +438,9 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
numReferences = rawReferenceAsJson.length;
|
numReferences = rawReferenceAsJson.length;
|
||||||
|
|
||||||
rawReferenceAsJson.forEach((reference, index) => {
|
rawReferenceAsJson.forEach((reference, index) => {
|
||||||
let polishedReference = generateReference(reference, index);
|
let polishedReference = generateReference(reference, index);
|
||||||
referenceSection.appendChild(polishedReference);
|
referenceSection.appendChild(polishedReference);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
numReferences += processOnlineReferences(referenceSection, rawReferenceAsJson);
|
numReferences += processOnlineReferences(referenceSection, rawReferenceAsJson);
|
||||||
}
|
}
|
||||||
@@ -542,7 +542,8 @@ To get started, just start typing below. You can also type / to see a list of co
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.detail) {
|
if (data.detail) {
|
||||||
// If the server returns a 500 error with detail, render a setup hint.
|
// If the server returns a 500 error with detail, render a setup hint.
|
||||||
renderMessage("Hi 👋🏾, to start chatting add available chat models options via <a class='inline-chat-link' href='/server/admin'>the Django Admin panel</a> on the Server", "khoj");
|
let setupMsg = "Hi 👋🏾, to start chatting add available chat models options via <a class='inline-chat-link' href='/server/admin'>the Django Admin panel</a> on the Server";
|
||||||
|
renderMessage(setupMsg, "khoj", null, null, true);
|
||||||
|
|
||||||
// Disable chat input field and update placeholder text
|
// Disable chat input field and update placeholder text
|
||||||
document.getElementById("chat-input").setAttribute("disabled", "disabled");
|
document.getElementById("chat-input").setAttribute("disabled", "disabled");
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<span class="card-title-text">Files</span>
|
<span class="card-title-text">Files</span>
|
||||||
<div class="instructions">
|
<div class="instructions">
|
||||||
<p class="card-description">Manage files from your computer</p>
|
<p class="card-description">Manage files from your computer</p>
|
||||||
<p id="get-desktop-client" class="card-description">Download the <a href="https://khoj.dev/downloads">Khoj Desktop app</a> to sync documents from your computer</p>
|
<p id="get-desktop-client" class="card-description">Get the Khoj <a href="https://khoj.dev/downloads">Desktop</a>, <a href="https://docs.khoj.dev/#/obsidian?id=setup">Obsidian</a> or <a href="https://docs.khoj.dev/#/emacs?id=setup">Emacs</a> app to sync documents from your computer</p>
|
||||||
</div>
|
</div>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="section-manage-files">
|
<div class="section-manage-files">
|
||||||
|
|||||||
@@ -884,3 +884,8 @@ async def extract_references_and_questions(
|
|||||||
compiled_references = [item.additional["compiled"] for item in result_list]
|
compiled_references = [item.additional["compiled"] for item in result_list]
|
||||||
|
|
||||||
return compiled_references, inferred_queries, defiltered_query
|
return compiled_references, inferred_queries, defiltered_query
|
||||||
|
|
||||||
|
|
||||||
|
@api.get("/health")
|
||||||
|
async def health_check():
|
||||||
|
return Response(status_code=200)
|
||||||
|
|||||||
@@ -29,5 +29,6 @@
|
|||||||
"0.14.0": "0.15.0",
|
"0.14.0": "0.15.0",
|
||||||
"1.0.0": "0.15.0",
|
"1.0.0": "0.15.0",
|
||||||
"1.0.1": "0.15.0",
|
"1.0.1": "0.15.0",
|
||||||
"1.1.0": "0.15.0"
|
"1.1.0": "0.15.0",
|
||||||
|
"1.2.0": "0.15.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user