khoj 1.16.1.dev25__py3-none-any.whl → 1.17.1.dev216__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- khoj/configure.py +6 -6
- khoj/database/adapters/__init__.py +55 -26
- khoj/database/migrations/0053_agent_style_color_agent_style_icon.py +61 -0
- khoj/database/models/__init__.py +35 -0
- khoj/interface/web/assets/icons/favicon-128x128.png +0 -0
- khoj/interface/web/assets/icons/favicon-256x256.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways-200.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways-500.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways.svg +31 -5384
- khoj/interface/web/assets/icons/khoj.svg +26 -0
- khoj/interface/web/chat.html +191 -301
- khoj/interface/web/content_source_computer_input.html +3 -3
- khoj/interface/web/content_source_github_input.html +1 -1
- khoj/interface/web/content_source_notion_input.html +1 -1
- khoj/interface/web/public_conversation.html +1 -1
- khoj/interface/web/search.html +2 -2
- khoj/interface/web/{config.html → settings.html} +30 -30
- khoj/interface/web/utils.html +1 -1
- khoj/processor/content/docx/docx_to_entries.py +4 -9
- khoj/processor/content/github/github_to_entries.py +1 -3
- khoj/processor/content/images/image_to_entries.py +4 -9
- khoj/processor/content/markdown/markdown_to_entries.py +4 -9
- khoj/processor/content/notion/notion_to_entries.py +1 -3
- khoj/processor/content/org_mode/org_to_entries.py +4 -9
- khoj/processor/content/pdf/pdf_to_entries.py +4 -9
- khoj/processor/content/plaintext/plaintext_to_entries.py +4 -9
- khoj/processor/content/text_to_entries.py +1 -3
- khoj/processor/conversation/utils.py +0 -4
- khoj/processor/tools/online_search.py +13 -7
- khoj/routers/api.py +58 -9
- khoj/routers/api_agents.py +3 -1
- khoj/routers/api_chat.py +335 -562
- khoj/routers/api_content.py +538 -0
- khoj/routers/api_model.py +156 -0
- khoj/routers/helpers.py +338 -23
- khoj/routers/notion.py +2 -8
- khoj/routers/web_client.py +43 -256
- khoj/search_type/text_search.py +5 -4
- khoj/utils/fs_syncer.py +4 -2
- khoj/utils/rawconfig.py +6 -1
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/METADATA +2 -2
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/RECORD +45 -43
- khoj/routers/api_config.py +0 -434
- khoj/routers/indexer.py +0 -349
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/WHEEL +0 -0
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/entry_points.txt +0 -0
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/licenses/LICENSE +0 -0
khoj/configure.py
CHANGED
|
@@ -42,7 +42,7 @@ from khoj.database.adapters import (
|
|
|
42
42
|
)
|
|
43
43
|
from khoj.database.models import ClientApplication, KhojUser, ProcessLock, Subscription
|
|
44
44
|
from khoj.processor.embeddings import CrossEncoderModel, EmbeddingsModel
|
|
45
|
-
from khoj.routers.
|
|
45
|
+
from khoj.routers.api_content import configure_content, configure_search
|
|
46
46
|
from khoj.routers.twilio import is_twilio_enabled
|
|
47
47
|
from khoj.utils import constants, state
|
|
48
48
|
from khoj.utils.config import SearchType
|
|
@@ -308,16 +308,16 @@ def configure_routes(app):
|
|
|
308
308
|
from khoj.routers.api import api
|
|
309
309
|
from khoj.routers.api_agents import api_agents
|
|
310
310
|
from khoj.routers.api_chat import api_chat
|
|
311
|
-
from khoj.routers.
|
|
312
|
-
from khoj.routers.
|
|
311
|
+
from khoj.routers.api_content import api_content
|
|
312
|
+
from khoj.routers.api_model import api_model
|
|
313
313
|
from khoj.routers.notion import notion_router
|
|
314
314
|
from khoj.routers.web_client import web_client
|
|
315
315
|
|
|
316
316
|
app.include_router(api, prefix="/api")
|
|
317
317
|
app.include_router(api_chat, prefix="/api/chat")
|
|
318
318
|
app.include_router(api_agents, prefix="/api/agents")
|
|
319
|
-
app.include_router(
|
|
320
|
-
app.include_router(
|
|
319
|
+
app.include_router(api_model, prefix="/api/model")
|
|
320
|
+
app.include_router(api_content, prefix="/api/content")
|
|
321
321
|
app.include_router(notion_router, prefix="/api/notion")
|
|
322
322
|
app.include_router(web_client)
|
|
323
323
|
|
|
@@ -336,7 +336,7 @@ def configure_routes(app):
|
|
|
336
336
|
if is_twilio_enabled():
|
|
337
337
|
from khoj.routers.api_phone import api_phone
|
|
338
338
|
|
|
339
|
-
app.include_router(api_phone, prefix="/api/
|
|
339
|
+
app.include_router(api_phone, prefix="/api/phone")
|
|
340
340
|
logger.info("📞 Enabled Twilio")
|
|
341
341
|
|
|
342
342
|
|
|
@@ -645,7 +645,11 @@ class ConversationAdapters:
|
|
|
645
645
|
|
|
646
646
|
@staticmethod
|
|
647
647
|
def get_conversation_sessions(user: KhojUser, client_application: ClientApplication = None):
|
|
648
|
-
return
|
|
648
|
+
return (
|
|
649
|
+
Conversation.objects.filter(user=user, client=client_application)
|
|
650
|
+
.prefetch_related("agent")
|
|
651
|
+
.order_by("-updated_at")
|
|
652
|
+
)
|
|
649
653
|
|
|
650
654
|
@staticmethod
|
|
651
655
|
async def aset_conversation_title(
|
|
@@ -680,34 +684,18 @@ class ConversationAdapters:
|
|
|
680
684
|
async def aget_conversation_by_user(
|
|
681
685
|
user: KhojUser, client_application: ClientApplication = None, conversation_id: int = None, title: str = None
|
|
682
686
|
) -> Optional[Conversation]:
|
|
687
|
+
query = Conversation.objects.filter(user=user, client=client_application).prefetch_related("agent")
|
|
688
|
+
|
|
683
689
|
if conversation_id:
|
|
684
|
-
return (
|
|
685
|
-
await Conversation.objects.filter(user=user, client=client_application, id=conversation_id)
|
|
686
|
-
.prefetch_related("agent")
|
|
687
|
-
.afirst()
|
|
688
|
-
)
|
|
690
|
+
return await query.filter(id=conversation_id).afirst()
|
|
689
691
|
elif title:
|
|
690
|
-
return (
|
|
691
|
-
await Conversation.objects.filter(user=user, client=client_application, title=title)
|
|
692
|
-
.prefetch_related("agent")
|
|
693
|
-
.afirst()
|
|
694
|
-
)
|
|
695
|
-
else:
|
|
696
|
-
conversation = (
|
|
697
|
-
Conversation.objects.filter(user=user, client=client_application)
|
|
698
|
-
.prefetch_related("agent")
|
|
699
|
-
.order_by("-updated_at")
|
|
700
|
-
)
|
|
692
|
+
return await query.filter(title=title).afirst()
|
|
701
693
|
|
|
702
|
-
|
|
703
|
-
return await conversation.prefetch_related("agent").afirst()
|
|
694
|
+
conversation = await query.order_by("-updated_at").afirst()
|
|
704
695
|
|
|
705
|
-
return await (
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
.order_by("-updated_at")
|
|
709
|
-
.afirst()
|
|
710
|
-
) or await Conversation.objects.prefetch_related("agent").acreate(user=user, client=client_application)
|
|
696
|
+
return conversation or await Conversation.objects.prefetch_related("agent").acreate(
|
|
697
|
+
user=user, client=client_application
|
|
698
|
+
)
|
|
711
699
|
|
|
712
700
|
@staticmethod
|
|
713
701
|
async def adelete_conversation_by_user(
|
|
@@ -814,11 +802,14 @@ class ConversationAdapters:
|
|
|
814
802
|
def create_conversation_from_public_conversation(
|
|
815
803
|
user: KhojUser, public_conversation: PublicConversation, client_app: ClientApplication
|
|
816
804
|
):
|
|
805
|
+
scrubbed_title = public_conversation.title if public_conversation.title else public_conversation.slug
|
|
806
|
+
if scrubbed_title:
|
|
807
|
+
scrubbed_title = scrubbed_title.replace("-", " ")
|
|
817
808
|
return Conversation.objects.create(
|
|
818
809
|
user=user,
|
|
819
810
|
conversation_log=public_conversation.conversation_log,
|
|
820
811
|
client=client_app,
|
|
821
|
-
slug=
|
|
812
|
+
slug=scrubbed_title,
|
|
822
813
|
title=public_conversation.title,
|
|
823
814
|
agent=public_conversation.agent,
|
|
824
815
|
)
|
|
@@ -959,6 +950,34 @@ class ConversationAdapters:
|
|
|
959
950
|
)
|
|
960
951
|
return new_config
|
|
961
952
|
|
|
953
|
+
@staticmethod
|
|
954
|
+
def add_files_to_filter(user: KhojUser, conversation_id: int, files: List[str]):
|
|
955
|
+
conversation = ConversationAdapters.get_conversation_by_user(user, conversation_id=conversation_id)
|
|
956
|
+
file_list = EntryAdapters.get_all_filenames_by_source(user, "computer")
|
|
957
|
+
for filename in files:
|
|
958
|
+
if filename in file_list and filename not in conversation.file_filters:
|
|
959
|
+
conversation.file_filters.append(filename)
|
|
960
|
+
conversation.save()
|
|
961
|
+
|
|
962
|
+
# remove files from conversation.file_filters that are not in file_list
|
|
963
|
+
conversation.file_filters = [file for file in conversation.file_filters if file in file_list]
|
|
964
|
+
conversation.save()
|
|
965
|
+
return conversation.file_filters
|
|
966
|
+
|
|
967
|
+
@staticmethod
|
|
968
|
+
def remove_files_from_filter(user: KhojUser, conversation_id: int, files: List[str]):
|
|
969
|
+
conversation = ConversationAdapters.get_conversation_by_user(user, conversation_id=conversation_id)
|
|
970
|
+
for filename in files:
|
|
971
|
+
if filename in conversation.file_filters:
|
|
972
|
+
conversation.file_filters.remove(filename)
|
|
973
|
+
conversation.save()
|
|
974
|
+
|
|
975
|
+
# remove files from conversation.file_filters that are not in file_list
|
|
976
|
+
file_list = EntryAdapters.get_all_filenames_by_source(user, "computer")
|
|
977
|
+
conversation.file_filters = [file for file in conversation.file_filters if file in file_list]
|
|
978
|
+
conversation.save()
|
|
979
|
+
return conversation.file_filters
|
|
980
|
+
|
|
962
981
|
|
|
963
982
|
class FileObjectAdapters:
|
|
964
983
|
@staticmethod
|
|
@@ -1087,6 +1106,16 @@ class EntryAdapters:
|
|
|
1087
1106
|
async def adelete_entry_by_file(user: KhojUser, file_path: str):
|
|
1088
1107
|
return await Entry.objects.filter(user=user, file_path=file_path).adelete()
|
|
1089
1108
|
|
|
1109
|
+
@staticmethod
|
|
1110
|
+
async def adelete_entries_by_filenames(user: KhojUser, filenames: List[str], batch_size=1000):
|
|
1111
|
+
deleted_count = 0
|
|
1112
|
+
for i in range(0, len(filenames), batch_size):
|
|
1113
|
+
batch = filenames[i : i + batch_size]
|
|
1114
|
+
count, _ = await Entry.objects.filter(user=user, file_path__in=batch).adelete()
|
|
1115
|
+
deleted_count += count
|
|
1116
|
+
|
|
1117
|
+
return deleted_count
|
|
1118
|
+
|
|
1090
1119
|
@staticmethod
|
|
1091
1120
|
def get_all_filenames_by_source(user: KhojUser, file_source: str):
|
|
1092
1121
|
return (
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Generated by Django 5.0.6 on 2024-07-13 16:26
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("database", "0052_alter_searchmodelconfig_bi_encoder_docs_encode_config_and_more"),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
operations = [
|
|
12
|
+
migrations.AddField(
|
|
13
|
+
model_name="agent",
|
|
14
|
+
name="style_color",
|
|
15
|
+
field=models.CharField(
|
|
16
|
+
choices=[
|
|
17
|
+
("blue", "Blue"),
|
|
18
|
+
("green", "Green"),
|
|
19
|
+
("red", "Red"),
|
|
20
|
+
("yellow", "Yellow"),
|
|
21
|
+
("orange", "Orange"),
|
|
22
|
+
("purple", "Purple"),
|
|
23
|
+
("pink", "Pink"),
|
|
24
|
+
("teal", "Teal"),
|
|
25
|
+
("cyan", "Cyan"),
|
|
26
|
+
("lime", "Lime"),
|
|
27
|
+
("indigo", "Indigo"),
|
|
28
|
+
("fuschia", "Fuschia"),
|
|
29
|
+
("rose", "Rose"),
|
|
30
|
+
("sky", "Sky"),
|
|
31
|
+
("amber", "Amber"),
|
|
32
|
+
("emerald", "Emerald"),
|
|
33
|
+
],
|
|
34
|
+
default="blue",
|
|
35
|
+
max_length=200,
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
migrations.AddField(
|
|
39
|
+
model_name="agent",
|
|
40
|
+
name="style_icon",
|
|
41
|
+
field=models.CharField(
|
|
42
|
+
choices=[
|
|
43
|
+
("Lightbulb", "Lighbulb"),
|
|
44
|
+
("Health", "Health"),
|
|
45
|
+
("Robot", "Robot"),
|
|
46
|
+
("Aperture", "Aperture"),
|
|
47
|
+
("GraduationCap", "Graduation Cap"),
|
|
48
|
+
("Jeep", "Jeep"),
|
|
49
|
+
("Island", "Island"),
|
|
50
|
+
("MathOperations", "Math Operations"),
|
|
51
|
+
("Asclepius", "Asclepius"),
|
|
52
|
+
("Couch", "Couch"),
|
|
53
|
+
("Code", "Code"),
|
|
54
|
+
("Atom", "Atom"),
|
|
55
|
+
("ClockCounterClockwise", "Clock Counter Clockwise"),
|
|
56
|
+
],
|
|
57
|
+
default="Lightbulb",
|
|
58
|
+
max_length=200,
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
]
|
khoj/database/models/__init__.py
CHANGED
|
@@ -103,6 +103,39 @@ class VoiceModelOption(BaseModel):
|
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
class Agent(BaseModel):
|
|
106
|
+
class StyleColorTypes(models.TextChoices):
|
|
107
|
+
BLUE = "blue"
|
|
108
|
+
GREEN = "green"
|
|
109
|
+
RED = "red"
|
|
110
|
+
YELLOW = "yellow"
|
|
111
|
+
ORANGE = "orange"
|
|
112
|
+
PURPLE = "purple"
|
|
113
|
+
PINK = "pink"
|
|
114
|
+
TEAL = "teal"
|
|
115
|
+
CYAN = "cyan"
|
|
116
|
+
LIME = "lime"
|
|
117
|
+
INDIGO = "indigo"
|
|
118
|
+
FUSCHIA = "fuschia"
|
|
119
|
+
ROSE = "rose"
|
|
120
|
+
SKY = "sky"
|
|
121
|
+
AMBER = "amber"
|
|
122
|
+
EMERALD = "emerald"
|
|
123
|
+
|
|
124
|
+
class StyleIconTypes(models.TextChoices):
|
|
125
|
+
LIGHBULB = "Lightbulb"
|
|
126
|
+
HEALTH = "Health"
|
|
127
|
+
ROBOT = "Robot"
|
|
128
|
+
APERTURE = "Aperture"
|
|
129
|
+
GRADUATION_CAP = "GraduationCap"
|
|
130
|
+
JEEP = "Jeep"
|
|
131
|
+
ISLAND = "Island"
|
|
132
|
+
MATH_OPERATIONS = "MathOperations"
|
|
133
|
+
ASCLEPIUS = "Asclepius"
|
|
134
|
+
COUCH = "Couch"
|
|
135
|
+
CODE = "Code"
|
|
136
|
+
ATOM = "Atom"
|
|
137
|
+
CLOCK_COUNTER_CLOCKWISE = "ClockCounterClockwise"
|
|
138
|
+
|
|
106
139
|
creator = models.ForeignKey(
|
|
107
140
|
KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True
|
|
108
141
|
) # Creator will only be null when the agents are managed by admin
|
|
@@ -114,6 +147,8 @@ class Agent(BaseModel):
|
|
|
114
147
|
managed_by_admin = models.BooleanField(default=False)
|
|
115
148
|
chat_model = models.ForeignKey(ChatModelOptions, on_delete=models.CASCADE)
|
|
116
149
|
slug = models.CharField(max_length=200)
|
|
150
|
+
style_color = models.CharField(max_length=200, choices=StyleColorTypes.choices, default=StyleColorTypes.BLUE)
|
|
151
|
+
style_icon = models.CharField(max_length=200, choices=StyleIconTypes.choices, default=StyleIconTypes.LIGHBULB)
|
|
117
152
|
|
|
118
153
|
|
|
119
154
|
class ProcessLock(BaseModel):
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|