khoj 1.30.11.dev13__py3-none-any.whl → 1.30.11.dev46__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.
Files changed (78) hide show
  1. khoj/app/settings.py +21 -0
  2. khoj/database/admin.py +47 -37
  3. khoj/database/migrations/0075_migrate_generated_assets_and_validate.py +85 -0
  4. khoj/database/models/__init__.py +164 -31
  5. khoj/interface/compiled/404/index.html +1 -1
  6. khoj/interface/compiled/_next/static/chunks/1603-f5babe72ba9f6a59.js +1 -0
  7. khoj/interface/compiled/_next/static/chunks/5538-0ea2d3944ca051e1.js +1 -0
  8. khoj/interface/compiled/_next/static/chunks/app/agents/layout-1878cc328ea380bd.js +1 -0
  9. khoj/interface/compiled/_next/static/chunks/app/agents/{page-8eead7920b0ff92a.js → page-f5c0801b27a8e95e.js} +1 -1
  10. khoj/interface/compiled/_next/static/chunks/app/automations/{page-b5800b5286306140.js → page-8691f6c09a0acd44.js} +1 -1
  11. khoj/interface/compiled/_next/static/chunks/app/chat/layout-9219a85f3477e722.js +1 -0
  12. khoj/interface/compiled/_next/static/chunks/app/chat/{page-d7d2ab93e519f0b2.js → page-135d56dd4263e40d.js} +1 -1
  13. khoj/interface/compiled/_next/static/chunks/app/layout-6310c57b674dd6f5.js +1 -0
  14. khoj/interface/compiled/_next/static/chunks/app/{page-3c32ad5472f75965.js → page-e79ace822d51557b.js} +1 -1
  15. khoj/interface/compiled/_next/static/chunks/app/search/{page-faa998c71eb7ca8e.js → page-e8b578d155550386.js} +1 -1
  16. khoj/interface/compiled/_next/static/chunks/app/settings/{page-cbe7f56b1f87d77a.js → page-b6c835050c970be7.js} +1 -1
  17. khoj/interface/compiled/_next/static/chunks/app/share/chat/layout-6f4879fbbf8b90f7.js +1 -0
  18. khoj/interface/compiled/_next/static/chunks/app/share/chat/{page-cd5757199539bbf2.js → page-635635e4fb39fe29.js} +1 -1
  19. khoj/interface/compiled/_next/static/chunks/{webpack-3a2dfd74acf6e193.js → webpack-5203c3872078c10c.js} +1 -1
  20. khoj/interface/compiled/_next/static/css/{bedf49fbfc598358.css → 089de1d8526b96e9.css} +1 -1
  21. khoj/interface/compiled/_next/static/css/4cae6c0e5c72fb2d.css +1 -0
  22. khoj/interface/compiled/_next/static/css/edd3abaf11580924.css +1 -0
  23. khoj/interface/compiled/_next/static/media/1d8a05b60287ae6c-s.p.woff2 +0 -0
  24. khoj/interface/compiled/_next/static/media/6f22fce21a7c433c-s.woff2 +0 -0
  25. khoj/interface/compiled/_next/static/media/77c207b095007c34-s.p.woff2 +0 -0
  26. khoj/interface/compiled/_next/static/media/82ef96de0e8f4d8c-s.p.woff2 +0 -0
  27. khoj/interface/compiled/_next/static/media/a6ecd16fa044d500-s.p.woff2 +0 -0
  28. khoj/interface/compiled/_next/static/media/bd82c78e5b7b3fe9-s.p.woff2 +0 -0
  29. khoj/interface/compiled/_next/static/media/c32c8052c071fc42-s.woff2 +0 -0
  30. khoj/interface/compiled/_next/static/media/c4250770ab8708b6-s.p.woff2 +0 -0
  31. khoj/interface/compiled/agents/index.html +1 -1
  32. khoj/interface/compiled/agents/index.txt +2 -2
  33. khoj/interface/compiled/assets/icons/khoj_lantern.svg +100 -0
  34. khoj/interface/compiled/assets/icons/khoj_lantern_128x128_dark.png +0 -0
  35. khoj/interface/compiled/automations/index.html +1 -1
  36. khoj/interface/compiled/automations/index.txt +2 -2
  37. khoj/interface/compiled/chat/index.html +1 -1
  38. khoj/interface/compiled/chat/index.txt +2 -2
  39. khoj/interface/compiled/index.html +1 -1
  40. khoj/interface/compiled/index.txt +2 -2
  41. khoj/interface/compiled/search/index.html +1 -1
  42. khoj/interface/compiled/search/index.txt +2 -2
  43. khoj/interface/compiled/settings/index.html +1 -1
  44. khoj/interface/compiled/settings/index.txt +2 -2
  45. khoj/interface/compiled/share/chat/index.html +1 -1
  46. khoj/interface/compiled/share/chat/index.txt +2 -2
  47. khoj/processor/conversation/anthropic/anthropic_chat.py +11 -3
  48. khoj/processor/conversation/google/gemini_chat.py +11 -3
  49. khoj/processor/conversation/offline/chat_model.py +6 -2
  50. khoj/processor/conversation/openai/gpt.py +10 -2
  51. khoj/processor/conversation/prompts.py +18 -0
  52. khoj/processor/conversation/utils.py +82 -26
  53. khoj/processor/image/generate.py +10 -13
  54. khoj/routers/api_chat.py +49 -98
  55. khoj/routers/helpers.py +41 -1
  56. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev46.dist-info}/METADATA +2 -1
  57. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev46.dist-info}/RECORD +62 -59
  58. khoj/interface/compiled/_next/static/chunks/1603-c68d44bc4ae6039a.js +0 -1
  59. khoj/interface/compiled/_next/static/chunks/5538-e5f3c9f4d67a64b9.js +0 -1
  60. khoj/interface/compiled/_next/static/chunks/app/agents/layout-f2ea2b26fc0e78b1.js +0 -1
  61. khoj/interface/compiled/_next/static/chunks/app/chat/layout-1072c3b0ab136e74.js +0 -1
  62. khoj/interface/compiled/_next/static/chunks/app/layout-72ec1be8afd0b1ab.js +0 -1
  63. khoj/interface/compiled/_next/static/chunks/app/share/chat/layout-dc97434f0354a74e.js +0 -1
  64. khoj/interface/compiled/_next/static/css/2d097a35da6bfe8d.css +0 -1
  65. khoj/interface/compiled/_next/static/css/80bd6301fc657983.css +0 -1
  66. khoj/interface/compiled/_next/static/media/5455839c73f146e7-s.p.woff2 +0 -0
  67. khoj/interface/compiled/_next/static/media/5984b96ba4822821-s.p.woff2 +0 -0
  68. khoj/interface/compiled/_next/static/media/684adc3dde1b03f1-s.p.woff2 +0 -0
  69. khoj/interface/compiled/_next/static/media/82e3b9a1bdaf0c26-s.p.woff2 +0 -0
  70. khoj/interface/compiled/_next/static/media/8d1ea331386a0db8-s.p.woff2 +0 -0
  71. khoj/interface/compiled/_next/static/media/91475f6526542a4f-s.woff2 +0 -0
  72. khoj/interface/compiled/_next/static/media/b98b13dbc1c3b59c-s.p.woff2 +0 -0
  73. khoj/interface/compiled/_next/static/media/c824d7a20139e39d-s.woff2 +0 -0
  74. /khoj/interface/compiled/_next/static/{K_WyVARSz0loPVvwOW1gg → VhbBwTudxbu82AwZhVKwF}/_buildManifest.js +0 -0
  75. /khoj/interface/compiled/_next/static/{K_WyVARSz0loPVvwOW1gg → VhbBwTudxbu82AwZhVKwF}/_ssgManifest.js +0 -0
  76. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev46.dist-info}/WHEEL +0 -0
  77. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev46.dist-info}/entry_points.txt +0 -0
  78. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev46.dist-info}/licenses/LICENSE +0 -0
khoj/app/settings.py CHANGED
@@ -13,6 +13,8 @@ https://docs.djangoproject.com/en/4.2/ref/settings/
13
13
  import os
14
14
  from pathlib import Path
15
15
 
16
+ from django.templatetags.static import static
17
+
16
18
  from khoj.utils.helpers import in_debug_mode, is_env_var_true
17
19
 
18
20
  # Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -72,6 +74,7 @@ INSTALLED_APPS = [
72
74
  "django.contrib.auth",
73
75
  "django.contrib.contenttypes",
74
76
  "khoj.database.apps.DatabaseConfig",
77
+ "unfold",
75
78
  "django.contrib.admin",
76
79
  "django.contrib.sessions",
77
80
  "django.contrib.messages",
@@ -195,3 +198,21 @@ APSCHEDULER_DATETIME_FORMAT = "N j, Y, f:s a"
195
198
  # that supports multiple background worker processes instead (e.g. Dramatiq, Celery, Django-RQ,
196
199
  # etc. See: https://djangopackages.org/grids/g/workers-queues-tasks/ for popular options).
197
200
  APSCHEDULER_RUN_NOW_TIMEOUT = 240 # Seconds
201
+
202
+ UNFOLD = {
203
+ "SITE_TITLE": "Khoj Admin Panel",
204
+ "SITE_HEADER": "Khoj Admin Panel",
205
+ "SITE_URL": "/",
206
+ "SITE_ICON": {
207
+ "light": lambda request: static("assets/icons/khoj_lantern_128x128.png"),
208
+ "dark": lambda request: static("assets/icons/khoj_lantern_128x128_dark.png"),
209
+ },
210
+ "SITE_FAVICONS": [
211
+ {
212
+ "rel": "icon",
213
+ "sizes": "32x32",
214
+ "type": "image/svg+xml",
215
+ "href": lambda request: static("assets/icons/khoj_lantern.svg"),
216
+ },
217
+ ],
218
+ }
khoj/database/admin.py CHANGED
@@ -4,11 +4,14 @@ from datetime import date, datetime, timedelta, timezone
4
4
 
5
5
  from apscheduler.job import Job
6
6
  from django.contrib import admin, messages
7
- from django.contrib.auth.admin import UserAdmin
7
+ from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
8
+ from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
9
+ from django.contrib.auth.models import Group
8
10
  from django.http import HttpResponse
9
- from django_apscheduler.admin import DjangoJobAdmin
11
+ from django_apscheduler.admin import DjangoJobAdmin, DjangoJobExecutionAdmin
10
12
  from django_apscheduler.jobstores import DjangoJobStore
11
- from django_apscheduler.models import DjangoJob
13
+ from django_apscheduler.models import DjangoJob, DjangoJobExecution
14
+ from unfold import admin as unfold_admin
12
15
 
13
16
  from khoj.database.models import (
14
17
  Agent,
@@ -35,10 +38,8 @@ from khoj.database.models import (
35
38
  )
36
39
  from khoj.utils.helpers import ImageIntentType
37
40
 
38
- admin.site.unregister(DjangoJob)
39
-
40
41
 
41
- class KhojDjangoJobAdmin(DjangoJobAdmin):
42
+ class KhojDjangoJobAdmin(DjangoJobAdmin, unfold_admin.ModelAdmin):
42
43
  list_display = (
43
44
  "id",
44
45
  "next_run_time",
@@ -62,10 +63,25 @@ class KhojDjangoJobAdmin(DjangoJobAdmin):
62
63
  return queryset, use_distinct
63
64
 
64
65
 
66
+ class KhojDjangoJobExecutionAdmin(DjangoJobExecutionAdmin, unfold_admin.ModelAdmin):
67
+ pass
68
+
69
+
70
+ admin.site.unregister(DjangoJob)
65
71
  admin.site.register(DjangoJob, KhojDjangoJobAdmin)
72
+ admin.site.unregister(DjangoJobExecution)
73
+ admin.site.register(DjangoJobExecution, KhojDjangoJobExecutionAdmin)
66
74
 
67
75
 
68
- class KhojUserAdmin(UserAdmin):
76
+ class GroupAdmin(BaseGroupAdmin, unfold_admin.ModelAdmin):
77
+ pass
78
+
79
+
80
+ class UserAdmin(BaseUserAdmin, unfold_admin.ModelAdmin):
81
+ pass
82
+
83
+
84
+ class KhojUserAdmin(UserAdmin, unfold_admin.ModelAdmin):
69
85
  class DateJoinedAfterFilter(admin.SimpleListFilter):
70
86
  title = "Joined after"
71
87
  parameter_name = "joined_after"
@@ -137,21 +153,22 @@ class KhojUserAdmin(UserAdmin):
137
153
  get_email_login_url.short_description = "Get email login URL" # type: ignore
138
154
 
139
155
 
156
+ admin.site.unregister(Group)
140
157
  admin.site.register(KhojUser, KhojUserAdmin)
141
158
 
142
- admin.site.register(ProcessLock)
143
- admin.site.register(SpeechToTextModelOptions)
144
- admin.site.register(ReflectiveQuestion)
145
- admin.site.register(ClientApplication)
146
- admin.site.register(GithubConfig)
147
- admin.site.register(NotionConfig)
148
- admin.site.register(UserVoiceModelConfig)
149
- admin.site.register(VoiceModelOption)
150
- admin.site.register(UserRequests)
159
+ admin.site.register(ProcessLock, unfold_admin.ModelAdmin)
160
+ admin.site.register(SpeechToTextModelOptions, unfold_admin.ModelAdmin)
161
+ admin.site.register(ReflectiveQuestion, unfold_admin.ModelAdmin)
162
+ admin.site.register(ClientApplication, unfold_admin.ModelAdmin)
163
+ admin.site.register(GithubConfig, unfold_admin.ModelAdmin)
164
+ admin.site.register(NotionConfig, unfold_admin.ModelAdmin)
165
+ admin.site.register(UserVoiceModelConfig, unfold_admin.ModelAdmin)
166
+ admin.site.register(VoiceModelOption, unfold_admin.ModelAdmin)
167
+ admin.site.register(UserRequests, unfold_admin.ModelAdmin)
151
168
 
152
169
 
153
170
  @admin.register(Agent)
154
- class AgentAdmin(admin.ModelAdmin):
171
+ class AgentAdmin(unfold_admin.ModelAdmin):
155
172
  list_display = (
156
173
  "id",
157
174
  "name",
@@ -161,7 +178,7 @@ class AgentAdmin(admin.ModelAdmin):
161
178
 
162
179
 
163
180
  @admin.register(Entry)
164
- class EntryAdmin(admin.ModelAdmin):
181
+ class EntryAdmin(unfold_admin.ModelAdmin):
165
182
  list_display = (
166
183
  "id",
167
184
  "created_at",
@@ -183,7 +200,7 @@ class EntryAdmin(admin.ModelAdmin):
183
200
 
184
201
 
185
202
  @admin.register(Subscription)
186
- class KhojUserSubscription(admin.ModelAdmin):
203
+ class KhojUserSubscription(unfold_admin.ModelAdmin):
187
204
  list_display = (
188
205
  "id",
189
206
  "user",
@@ -195,7 +212,7 @@ class KhojUserSubscription(admin.ModelAdmin):
195
212
 
196
213
 
197
214
  @admin.register(ChatModelOptions)
198
- class ChatModelOptionsAdmin(admin.ModelAdmin):
215
+ class ChatModelOptionsAdmin(unfold_admin.ModelAdmin):
199
216
  list_display = (
200
217
  "id",
201
218
  "chat_model",
@@ -206,7 +223,7 @@ class ChatModelOptionsAdmin(admin.ModelAdmin):
206
223
 
207
224
 
208
225
  @admin.register(TextToImageModelConfig)
209
- class TextToImageModelOptionsAdmin(admin.ModelAdmin):
226
+ class TextToImageModelOptionsAdmin(unfold_admin.ModelAdmin):
210
227
  list_display = (
211
228
  "id",
212
229
  "model_name",
@@ -216,7 +233,7 @@ class TextToImageModelOptionsAdmin(admin.ModelAdmin):
216
233
 
217
234
 
218
235
  @admin.register(OpenAIProcessorConversationConfig)
219
- class OpenAIProcessorConversationConfigAdmin(admin.ModelAdmin):
236
+ class OpenAIProcessorConversationConfigAdmin(unfold_admin.ModelAdmin):
220
237
  list_display = (
221
238
  "id",
222
239
  "name",
@@ -227,7 +244,7 @@ class OpenAIProcessorConversationConfigAdmin(admin.ModelAdmin):
227
244
 
228
245
 
229
246
  @admin.register(SearchModelConfig)
230
- class SearchModelConfigAdmin(admin.ModelAdmin):
247
+ class SearchModelConfigAdmin(unfold_admin.ModelAdmin):
231
248
  list_display = (
232
249
  "id",
233
250
  "name",
@@ -238,7 +255,7 @@ class SearchModelConfigAdmin(admin.ModelAdmin):
238
255
 
239
256
 
240
257
  @admin.register(ServerChatSettings)
241
- class ServerChatSettingsAdmin(admin.ModelAdmin):
258
+ class ServerChatSettingsAdmin(unfold_admin.ModelAdmin):
242
259
  list_display = (
243
260
  "chat_default",
244
261
  "chat_advanced",
@@ -247,7 +264,7 @@ class ServerChatSettingsAdmin(admin.ModelAdmin):
247
264
 
248
265
 
249
266
  @admin.register(WebScraper)
250
- class WebScraperAdmin(admin.ModelAdmin):
267
+ class WebScraperAdmin(unfold_admin.ModelAdmin):
251
268
  list_display = (
252
269
  "priority",
253
270
  "name",
@@ -261,7 +278,7 @@ class WebScraperAdmin(admin.ModelAdmin):
261
278
 
262
279
 
263
280
  @admin.register(Conversation)
264
- class ConversationAdmin(admin.ModelAdmin):
281
+ class ConversationAdmin(unfold_admin.ModelAdmin):
265
282
  list_display = (
266
283
  "id",
267
284
  "user",
@@ -286,17 +303,10 @@ class ConversationAdmin(admin.ModelAdmin):
286
303
  modified_log = conversation.conversation_log
287
304
  chat_log = modified_log.get("chat", [])
288
305
  for idx, log in enumerate(chat_log):
289
- if (
290
- log["by"] == "khoj"
291
- and log["intent"]
292
- and log["intent"]["type"]
293
- and (
294
- log["intent"]["type"] == ImageIntentType.TEXT_TO_IMAGE.value
295
- or log["intent"]["type"] == ImageIntentType.TEXT_TO_IMAGE_V3.value
296
- )
297
- ):
298
- log["message"] = "inline image redacted for space"
306
+ if log["by"] == "khoj" and log["images"]:
307
+ log["images"] = ["inline image redacted for space"]
299
308
  chat_log[idx] = log
309
+
300
310
  modified_log["chat"] = chat_log
301
311
 
302
312
  writer.writerow(
@@ -367,7 +377,7 @@ class ConversationAdmin(admin.ModelAdmin):
367
377
 
368
378
 
369
379
  @admin.register(UserConversationConfig)
370
- class UserConversationConfigAdmin(admin.ModelAdmin):
380
+ class UserConversationConfigAdmin(unfold_admin.ModelAdmin):
371
381
  list_display = (
372
382
  "id",
373
383
  "get_user_email",
@@ -0,0 +1,85 @@
1
+ # Made manually by sabaimran for use by Django 5.0.9 on 2024-12-01 16:59
2
+
3
+ from django.db import migrations, models
4
+
5
+ # This script was written alongside when Pydantic validation was added to the Conversation conversation_log field.
6
+
7
+
8
+ def migrate_generated_assets(apps, schema_editor):
9
+ Conversation = apps.get_model("database", "Conversation")
10
+
11
+ # Process conversations in chunks
12
+ for conversation in Conversation.objects.iterator():
13
+ try:
14
+ meta_log = conversation.conversation_log
15
+ modified = False
16
+
17
+ for chat in meta_log.get("chat", []):
18
+ intent_type = chat.get("intent", {}).get("type")
19
+
20
+ if intent_type and chat["by"] == "khoj":
21
+ if intent_type and "text-to-image" in intent_type:
22
+ # Migrate the generated image to the new format
23
+ chat["images"] = [chat.get("message")]
24
+ chat["message"] = chat["intent"]["inferred-queries"][0]
25
+ modified = True
26
+
27
+ if intent_type and "excalidraw" in intent_type:
28
+ # Migrate the generated excalidraw to the new format
29
+ chat["excalidrawDiagram"] = chat.get("message")
30
+ chat["message"] = chat["intent"]["inferred-queries"][0]
31
+ modified = True
32
+
33
+ # Only save if changes were made
34
+ if modified:
35
+ conversation.conversation_log = meta_log
36
+ conversation.save()
37
+
38
+ except Exception as e:
39
+ print(f"Error processing conversation {conversation.id}: {str(e)}")
40
+ continue
41
+
42
+
43
+ def reverse_migration(apps, schema_editor):
44
+ Conversation = apps.get_model("database", "Conversation")
45
+
46
+ # Process conversations in chunks
47
+ for conversation in Conversation.objects.iterator():
48
+ try:
49
+ meta_log = conversation.conversation_log
50
+ modified = False
51
+
52
+ for chat in meta_log.get("chat", []):
53
+ intent_type = chat.get("intent", {}).get("type")
54
+
55
+ if intent_type and chat["by"] == "khoj":
56
+ if intent_type and "text-to-image" in intent_type:
57
+ # Migrate the generated image back to the old format
58
+ chat["message"] = chat.get("images", [])[0]
59
+ chat.pop("images", None)
60
+ modified = True
61
+
62
+ if intent_type and "excalidraw" in intent_type:
63
+ # Migrate the generated excalidraw back to the old format
64
+ chat["message"] = chat.get("excalidrawDiagram")
65
+ chat.pop("excalidrawDiagram", None)
66
+ modified = True
67
+
68
+ # Only save if changes were made
69
+ if modified:
70
+ conversation.conversation_log = meta_log
71
+ conversation.save()
72
+
73
+ except Exception as e:
74
+ print(f"Error processing conversation {conversation.id}: {str(e)}")
75
+ continue
76
+
77
+
78
+ class Migration(migrations.Migration):
79
+ dependencies = [
80
+ ("database", "0074_alter_conversation_title"),
81
+ ]
82
+
83
+ operations = [
84
+ migrations.RunPython(migrate_generated_assets, reverse_migration),
85
+ ]