khoj 1.30.11.dev13__py3-none-any.whl → 1.30.11.dev56__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 (89) hide show
  1. khoj/app/settings.py +21 -0
  2. khoj/configure.py +3 -3
  3. khoj/database/adapters/__init__.py +15 -15
  4. khoj/database/admin.py +50 -40
  5. khoj/database/migrations/0075_migrate_generated_assets_and_validate.py +85 -0
  6. khoj/database/migrations/0076_rename_openaiprocessorconversationconfig_aimodelapi_and_more.py +26 -0
  7. khoj/database/models/__init__.py +171 -42
  8. khoj/interface/compiled/404/index.html +1 -1
  9. khoj/interface/compiled/_next/static/chunks/1603-e40aadd1e56ab030.js +1 -0
  10. khoj/interface/compiled/_next/static/chunks/5538-0ea2d3944ca051e1.js +1 -0
  11. khoj/interface/compiled/_next/static/chunks/app/agents/layout-1878cc328ea380bd.js +1 -0
  12. khoj/interface/compiled/_next/static/chunks/app/agents/{page-8eead7920b0ff92a.js → page-f5c0801b27a8e95e.js} +1 -1
  13. khoj/interface/compiled/_next/static/chunks/app/automations/layout-7f1b79a2c67af0b4.js +1 -0
  14. khoj/interface/compiled/_next/static/chunks/app/automations/{page-b5800b5286306140.js → page-8691f6c09a0acd44.js} +1 -1
  15. khoj/interface/compiled/_next/static/chunks/app/chat/layout-9219a85f3477e722.js +1 -0
  16. khoj/interface/compiled/_next/static/chunks/app/chat/{page-d7d2ab93e519f0b2.js → page-135d56dd4263e40d.js} +1 -1
  17. khoj/interface/compiled/_next/static/chunks/app/layout-6310c57b674dd6f5.js +1 -0
  18. khoj/interface/compiled/_next/static/chunks/app/{page-3c32ad5472f75965.js → page-e79ace822d51557b.js} +1 -1
  19. khoj/interface/compiled/_next/static/chunks/app/search/{page-faa998c71eb7ca8e.js → page-e8b578d155550386.js} +1 -1
  20. khoj/interface/compiled/_next/static/chunks/app/settings/layout-f285795bc3154b8c.js +1 -0
  21. khoj/interface/compiled/_next/static/chunks/app/settings/{page-cbe7f56b1f87d77a.js → page-b6c835050c970be7.js} +1 -1
  22. khoj/interface/compiled/_next/static/chunks/app/share/chat/layout-6f4879fbbf8b90f7.js +1 -0
  23. khoj/interface/compiled/_next/static/chunks/app/share/chat/{page-cd5757199539bbf2.js → page-635635e4fb39fe29.js} +1 -1
  24. khoj/interface/compiled/_next/static/chunks/{webpack-3a2dfd74acf6e193.js → webpack-5203c3872078c10c.js} +1 -1
  25. khoj/interface/compiled/_next/static/css/{bedf49fbfc598358.css → 089de1d8526b96e9.css} +1 -1
  26. khoj/interface/compiled/_next/static/css/4cae6c0e5c72fb2d.css +1 -0
  27. khoj/interface/compiled/_next/static/css/edd3abaf11580924.css +1 -0
  28. khoj/interface/compiled/_next/static/media/1d8a05b60287ae6c-s.p.woff2 +0 -0
  29. khoj/interface/compiled/_next/static/media/6f22fce21a7c433c-s.woff2 +0 -0
  30. khoj/interface/compiled/_next/static/media/77c207b095007c34-s.p.woff2 +0 -0
  31. khoj/interface/compiled/_next/static/media/82ef96de0e8f4d8c-s.p.woff2 +0 -0
  32. khoj/interface/compiled/_next/static/media/a6ecd16fa044d500-s.p.woff2 +0 -0
  33. khoj/interface/compiled/_next/static/media/bd82c78e5b7b3fe9-s.p.woff2 +0 -0
  34. khoj/interface/compiled/_next/static/media/c32c8052c071fc42-s.woff2 +0 -0
  35. khoj/interface/compiled/_next/static/media/c4250770ab8708b6-s.p.woff2 +0 -0
  36. khoj/interface/compiled/agents/index.html +1 -1
  37. khoj/interface/compiled/agents/index.txt +2 -2
  38. khoj/interface/compiled/assets/icons/khoj_lantern.svg +100 -0
  39. khoj/interface/compiled/assets/icons/khoj_lantern_128x128_dark.png +0 -0
  40. khoj/interface/compiled/automations/index.html +1 -1
  41. khoj/interface/compiled/automations/index.txt +3 -3
  42. khoj/interface/compiled/chat/index.html +1 -1
  43. khoj/interface/compiled/chat/index.txt +2 -2
  44. khoj/interface/compiled/index.html +1 -1
  45. khoj/interface/compiled/index.txt +2 -2
  46. khoj/interface/compiled/search/index.html +1 -1
  47. khoj/interface/compiled/search/index.txt +2 -2
  48. khoj/interface/compiled/settings/index.html +1 -1
  49. khoj/interface/compiled/settings/index.txt +5 -4
  50. khoj/interface/compiled/share/chat/index.html +1 -1
  51. khoj/interface/compiled/share/chat/index.txt +2 -2
  52. khoj/migrations/migrate_server_pg.py +3 -9
  53. khoj/processor/conversation/anthropic/anthropic_chat.py +11 -3
  54. khoj/processor/conversation/google/gemini_chat.py +11 -3
  55. khoj/processor/conversation/offline/chat_model.py +6 -2
  56. khoj/processor/conversation/openai/gpt.py +10 -2
  57. khoj/processor/conversation/openai/utils.py +1 -6
  58. khoj/processor/conversation/prompts.py +18 -0
  59. khoj/processor/conversation/utils.py +82 -26
  60. khoj/processor/image/generate.py +12 -15
  61. khoj/routers/api.py +5 -5
  62. khoj/routers/api_chat.py +49 -98
  63. khoj/routers/helpers.py +52 -12
  64. khoj/utils/initialization.py +10 -12
  65. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev56.dist-info}/METADATA +2 -1
  66. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev56.dist-info}/RECORD +71 -67
  67. khoj/interface/compiled/_next/static/chunks/1603-c68d44bc4ae6039a.js +0 -1
  68. khoj/interface/compiled/_next/static/chunks/5538-e5f3c9f4d67a64b9.js +0 -1
  69. khoj/interface/compiled/_next/static/chunks/app/agents/layout-f2ea2b26fc0e78b1.js +0 -1
  70. khoj/interface/compiled/_next/static/chunks/app/automations/layout-f1050c1f20a3af67.js +0 -1
  71. khoj/interface/compiled/_next/static/chunks/app/chat/layout-1072c3b0ab136e74.js +0 -1
  72. khoj/interface/compiled/_next/static/chunks/app/layout-72ec1be8afd0b1ab.js +0 -1
  73. khoj/interface/compiled/_next/static/chunks/app/settings/layout-fe8a2f65ccafd142.js +0 -1
  74. khoj/interface/compiled/_next/static/chunks/app/share/chat/layout-dc97434f0354a74e.js +0 -1
  75. khoj/interface/compiled/_next/static/css/2d097a35da6bfe8d.css +0 -1
  76. khoj/interface/compiled/_next/static/css/80bd6301fc657983.css +0 -1
  77. khoj/interface/compiled/_next/static/media/5455839c73f146e7-s.p.woff2 +0 -0
  78. khoj/interface/compiled/_next/static/media/5984b96ba4822821-s.p.woff2 +0 -0
  79. khoj/interface/compiled/_next/static/media/684adc3dde1b03f1-s.p.woff2 +0 -0
  80. khoj/interface/compiled/_next/static/media/82e3b9a1bdaf0c26-s.p.woff2 +0 -0
  81. khoj/interface/compiled/_next/static/media/8d1ea331386a0db8-s.p.woff2 +0 -0
  82. khoj/interface/compiled/_next/static/media/91475f6526542a4f-s.woff2 +0 -0
  83. khoj/interface/compiled/_next/static/media/b98b13dbc1c3b59c-s.p.woff2 +0 -0
  84. khoj/interface/compiled/_next/static/media/c824d7a20139e39d-s.woff2 +0 -0
  85. /khoj/interface/compiled/_next/static/{K_WyVARSz0loPVvwOW1gg → J7Vqh1vjCleYuVLeTaJL6}/_buildManifest.js +0 -0
  86. /khoj/interface/compiled/_next/static/{K_WyVARSz0loPVvwOW1gg → J7Vqh1vjCleYuVLeTaJL6}/_ssgManifest.js +0 -0
  87. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev56.dist-info}/WHEEL +0 -0
  88. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev56.dist-info}/entry_points.txt +0 -0
  89. {khoj-1.30.11.dev13.dist-info → khoj-1.30.11.dev56.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,9 @@
1
+ import logging
1
2
  import os
2
3
  import re
3
4
  import uuid
4
5
  from random import choice
6
+ from typing import Dict, List, Optional, Union
5
7
 
6
8
  from django.contrib.auth.models import AbstractUser
7
9
  from django.contrib.postgres.fields import ArrayField
@@ -11,9 +13,109 @@ from django.db.models.signals import pre_save
11
13
  from django.dispatch import receiver
12
14
  from pgvector.django import VectorField
13
15
  from phonenumber_field.modelfields import PhoneNumberField
16
+ from pydantic import BaseModel as PydanticBaseModel
17
+ from pydantic import Field
14
18
 
19
+ logger = logging.getLogger(__name__)
15
20
 
16
- class BaseModel(models.Model):
21
+
22
+ # Pydantic models for type Chat Message validation
23
+ class Context(PydanticBaseModel):
24
+ compiled: str
25
+ file: str
26
+
27
+
28
+ class CodeContextFile(PydanticBaseModel):
29
+ filename: str
30
+ b64_data: str
31
+
32
+
33
+ class CodeContextResult(PydanticBaseModel):
34
+ success: bool
35
+ output_files: List[CodeContextFile]
36
+ std_out: str
37
+ std_err: str
38
+ code_runtime: int
39
+
40
+
41
+ class CodeContextData(PydanticBaseModel):
42
+ code: str
43
+ result: Optional[CodeContextResult] = None
44
+
45
+
46
+ class WebPage(PydanticBaseModel):
47
+ link: str
48
+ query: Optional[str] = None
49
+ snippet: str
50
+
51
+
52
+ class AnswerBox(PydanticBaseModel):
53
+ link: Optional[str] = None
54
+ snippet: Optional[str] = None
55
+ title: str
56
+ snippetHighlighted: Optional[List[str]] = None
57
+
58
+
59
+ class PeopleAlsoAsk(PydanticBaseModel):
60
+ link: Optional[str] = None
61
+ question: Optional[str] = None
62
+ snippet: Optional[str] = None
63
+ title: str
64
+
65
+
66
+ class KnowledgeGraph(PydanticBaseModel):
67
+ attributes: Optional[Dict[str, str]] = None
68
+ description: Optional[str] = None
69
+ descriptionLink: Optional[str] = None
70
+ descriptionSource: Optional[str] = None
71
+ imageUrl: Optional[str] = None
72
+ title: str
73
+ type: Optional[str] = None
74
+
75
+
76
+ class OrganicContext(PydanticBaseModel):
77
+ snippet: str
78
+ title: str
79
+ link: str
80
+
81
+
82
+ class OnlineContext(PydanticBaseModel):
83
+ webpages: Optional[Union[WebPage, List[WebPage]]] = None
84
+ answerBox: Optional[AnswerBox] = None
85
+ peopleAlsoAsk: Optional[List[PeopleAlsoAsk]] = None
86
+ knowledgeGraph: Optional[KnowledgeGraph] = None
87
+ organicContext: Optional[List[OrganicContext]] = None
88
+
89
+
90
+ class Intent(PydanticBaseModel):
91
+ type: str
92
+ query: str
93
+ memory_type: str = Field(alias="memory-type")
94
+ inferred_queries: Optional[List[str]] = Field(default=None, alias="inferred-queries")
95
+
96
+
97
+ class TrainOfThought(PydanticBaseModel):
98
+ type: str
99
+ data: str
100
+
101
+
102
+ class ChatMessage(PydanticBaseModel):
103
+ message: str
104
+ trainOfThought: List[TrainOfThought] = []
105
+ context: List[Context] = []
106
+ onlineContext: Dict[str, OnlineContext] = {}
107
+ codeContext: Dict[str, CodeContextData] = {}
108
+ created: str
109
+ images: Optional[List[str]] = None
110
+ queryFiles: Optional[List[Dict]] = None
111
+ excalidrawDiagram: Optional[List[Dict]] = None
112
+ by: str
113
+ turnId: Optional[str] = None
114
+ intent: Optional[Intent] = None
115
+ automationId: Optional[str] = None
116
+
117
+
118
+ class DbBaseModel(models.Model):
17
119
  created_at = models.DateTimeField(auto_now_add=True)
18
120
  updated_at = models.DateTimeField(auto_now=True)
19
121
 
@@ -21,7 +123,7 @@ class BaseModel(models.Model):
21
123
  abstract = True
22
124
 
23
125
 
24
- class ClientApplication(BaseModel):
126
+ class ClientApplication(DbBaseModel):
25
127
  name = models.CharField(max_length=200)
26
128
  client_id = models.CharField(max_length=200)
27
129
  client_secret = models.CharField(max_length=200)
@@ -67,7 +169,7 @@ class KhojApiUser(models.Model):
67
169
  accessed_at = models.DateTimeField(null=True, default=None)
68
170
 
69
171
 
70
- class Subscription(BaseModel):
172
+ class Subscription(DbBaseModel):
71
173
  class Type(models.TextChoices):
72
174
  TRIAL = "trial"
73
175
  STANDARD = "standard"
@@ -79,13 +181,13 @@ class Subscription(BaseModel):
79
181
  enabled_trial_at = models.DateTimeField(null=True, default=None, blank=True)
80
182
 
81
183
 
82
- class OpenAIProcessorConversationConfig(BaseModel):
184
+ class AiModelApi(DbBaseModel):
83
185
  name = models.CharField(max_length=200)
84
186
  api_key = models.CharField(max_length=200)
85
187
  api_base_url = models.URLField(max_length=200, default=None, blank=True, null=True)
86
188
 
87
189
 
88
- class ChatModelOptions(BaseModel):
190
+ class ChatModelOptions(DbBaseModel):
89
191
  class ModelType(models.TextChoices):
90
192
  OPENAI = "openai"
91
193
  OFFLINE = "offline"
@@ -98,17 +200,15 @@ class ChatModelOptions(BaseModel):
98
200
  chat_model = models.CharField(max_length=200, default="bartowski/Meta-Llama-3.1-8B-Instruct-GGUF")
99
201
  model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.OFFLINE)
100
202
  vision_enabled = models.BooleanField(default=False)
101
- openai_config = models.ForeignKey(
102
- OpenAIProcessorConversationConfig, on_delete=models.CASCADE, default=None, null=True, blank=True
103
- )
203
+ ai_model_api = models.ForeignKey(AiModelApi, on_delete=models.CASCADE, default=None, null=True, blank=True)
104
204
 
105
205
 
106
- class VoiceModelOption(BaseModel):
206
+ class VoiceModelOption(DbBaseModel):
107
207
  model_id = models.CharField(max_length=200)
108
208
  name = models.CharField(max_length=200)
109
209
 
110
210
 
111
- class Agent(BaseModel):
211
+ class Agent(DbBaseModel):
112
212
  class StyleColorTypes(models.TextChoices):
113
213
  BLUE = "blue"
114
214
  GREEN = "green"
@@ -208,7 +308,7 @@ class Agent(BaseModel):
208
308
  super().save(*args, **kwargs)
209
309
 
210
310
 
211
- class ProcessLock(BaseModel):
311
+ class ProcessLock(DbBaseModel):
212
312
  class Operation(models.TextChoices):
213
313
  INDEX_CONTENT = "index_content"
214
314
  SCHEDULED_JOB = "scheduled_job"
@@ -231,24 +331,24 @@ def verify_agent(sender, instance, **kwargs):
231
331
  raise ValidationError(f"A private Agent with the name {instance.name} already exists.")
232
332
 
233
333
 
234
- class NotionConfig(BaseModel):
334
+ class NotionConfig(DbBaseModel):
235
335
  token = models.CharField(max_length=200)
236
336
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
237
337
 
238
338
 
239
- class GithubConfig(BaseModel):
339
+ class GithubConfig(DbBaseModel):
240
340
  pat_token = models.CharField(max_length=200)
241
341
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
242
342
 
243
343
 
244
- class GithubRepoConfig(BaseModel):
344
+ class GithubRepoConfig(DbBaseModel):
245
345
  name = models.CharField(max_length=200)
246
346
  owner = models.CharField(max_length=200)
247
347
  branch = models.CharField(max_length=200)
248
348
  github_config = models.ForeignKey(GithubConfig, on_delete=models.CASCADE, related_name="githubrepoconfig")
249
349
 
250
350
 
251
- class WebScraper(BaseModel):
351
+ class WebScraper(DbBaseModel):
252
352
  class WebScraperType(models.TextChoices):
253
353
  FIRECRAWL = "Firecrawl"
254
354
  OLOSTEP = "Olostep"
@@ -321,7 +421,7 @@ class WebScraper(BaseModel):
321
421
  super().save(*args, **kwargs)
322
422
 
323
423
 
324
- class ServerChatSettings(BaseModel):
424
+ class ServerChatSettings(DbBaseModel):
325
425
  chat_default = models.ForeignKey(
326
426
  ChatModelOptions, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="chat_default"
327
427
  )
@@ -333,35 +433,35 @@ class ServerChatSettings(BaseModel):
333
433
  )
334
434
 
335
435
 
336
- class LocalOrgConfig(BaseModel):
436
+ class LocalOrgConfig(DbBaseModel):
337
437
  input_files = models.JSONField(default=list, null=True)
338
438
  input_filter = models.JSONField(default=list, null=True)
339
439
  index_heading_entries = models.BooleanField(default=False)
340
440
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
341
441
 
342
442
 
343
- class LocalMarkdownConfig(BaseModel):
443
+ class LocalMarkdownConfig(DbBaseModel):
344
444
  input_files = models.JSONField(default=list, null=True)
345
445
  input_filter = models.JSONField(default=list, null=True)
346
446
  index_heading_entries = models.BooleanField(default=False)
347
447
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
348
448
 
349
449
 
350
- class LocalPdfConfig(BaseModel):
450
+ class LocalPdfConfig(DbBaseModel):
351
451
  input_files = models.JSONField(default=list, null=True)
352
452
  input_filter = models.JSONField(default=list, null=True)
353
453
  index_heading_entries = models.BooleanField(default=False)
354
454
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
355
455
 
356
456
 
357
- class LocalPlaintextConfig(BaseModel):
457
+ class LocalPlaintextConfig(DbBaseModel):
358
458
  input_files = models.JSONField(default=list, null=True)
359
459
  input_filter = models.JSONField(default=list, null=True)
360
460
  index_heading_entries = models.BooleanField(default=False)
361
461
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
362
462
 
363
463
 
364
- class SearchModelConfig(BaseModel):
464
+ class SearchModelConfig(DbBaseModel):
365
465
  class ModelType(models.TextChoices):
366
466
  TEXT = "text"
367
467
 
@@ -393,7 +493,7 @@ class SearchModelConfig(BaseModel):
393
493
  bi_encoder_confidence_threshold = models.FloatField(default=0.18)
394
494
 
395
495
 
396
- class TextToImageModelConfig(BaseModel):
496
+ class TextToImageModelConfig(DbBaseModel):
397
497
  class ModelType(models.TextChoices):
398
498
  OPENAI = "openai"
399
499
  STABILITYAI = "stability-ai"
@@ -402,26 +502,24 @@ class TextToImageModelConfig(BaseModel):
402
502
  model_name = models.CharField(max_length=200, default="dall-e-3")
403
503
  model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.OPENAI)
404
504
  api_key = models.CharField(max_length=200, default=None, null=True, blank=True)
405
- openai_config = models.ForeignKey(
406
- OpenAIProcessorConversationConfig, on_delete=models.CASCADE, default=None, null=True, blank=True
407
- )
505
+ ai_model_api = models.ForeignKey(AiModelApi, on_delete=models.CASCADE, default=None, null=True, blank=True)
408
506
 
409
507
  def clean(self):
410
508
  # Custom validation logic
411
509
  error = {}
412
510
  if self.model_type == self.ModelType.OPENAI:
413
- if self.api_key and self.openai_config:
511
+ if self.api_key and self.ai_model_api:
414
512
  error[
415
513
  "api_key"
416
- ] = "Both API key and OpenAI config cannot be set for OpenAI models. Please set only one of them."
514
+ ] = "Both API key and AI Model API cannot be set for OpenAI models. Please set only one of them."
417
515
  error[
418
- "openai_config"
516
+ "ai_model_api"
419
517
  ] = "Both API key and OpenAI config cannot be set for OpenAI models. Please set only one of them."
420
518
  if self.model_type != self.ModelType.OPENAI:
421
519
  if not self.api_key:
422
520
  error["api_key"] = "The API key field must be set for non OpenAI models."
423
- if self.openai_config:
424
- error["openai_config"] = "OpenAI config cannot be set for non OpenAI models."
521
+ if self.ai_model_api:
522
+ error["ai_model_api"] = "AI Model API cannot be set for non OpenAI models."
425
523
  if error:
426
524
  raise ValidationError(error)
427
525
 
@@ -430,7 +528,7 @@ class TextToImageModelConfig(BaseModel):
430
528
  super().save(*args, **kwargs)
431
529
 
432
530
 
433
- class SpeechToTextModelOptions(BaseModel):
531
+ class SpeechToTextModelOptions(DbBaseModel):
434
532
  class ModelType(models.TextChoices):
435
533
  OPENAI = "openai"
436
534
  OFFLINE = "offline"
@@ -439,22 +537,22 @@ class SpeechToTextModelOptions(BaseModel):
439
537
  model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.OFFLINE)
440
538
 
441
539
 
442
- class UserConversationConfig(BaseModel):
540
+ class UserConversationConfig(DbBaseModel):
443
541
  user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
444
542
  setting = models.ForeignKey(ChatModelOptions, on_delete=models.CASCADE, default=None, null=True, blank=True)
445
543
 
446
544
 
447
- class UserVoiceModelConfig(BaseModel):
545
+ class UserVoiceModelConfig(DbBaseModel):
448
546
  user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
449
547
  setting = models.ForeignKey(VoiceModelOption, on_delete=models.CASCADE, default=None, null=True, blank=True)
450
548
 
451
549
 
452
- class UserTextToImageModelConfig(BaseModel):
550
+ class UserTextToImageModelConfig(DbBaseModel):
453
551
  user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
454
552
  setting = models.ForeignKey(TextToImageModelConfig, on_delete=models.CASCADE)
455
553
 
456
554
 
457
- class Conversation(BaseModel):
555
+ class Conversation(DbBaseModel):
458
556
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
459
557
  conversation_log = models.JSONField(default=dict)
460
558
  client = models.ForeignKey(ClientApplication, on_delete=models.CASCADE, default=None, null=True, blank=True)
@@ -468,8 +566,39 @@ class Conversation(BaseModel):
468
566
  file_filters = models.JSONField(default=list)
469
567
  id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True, db_index=True)
470
568
 
569
+ def clean(self):
570
+ # Validate conversation_log structure
571
+ try:
572
+ messages = self.conversation_log.get("chat", [])
573
+ for msg in messages:
574
+ ChatMessage.model_validate(msg)
575
+ except Exception as e:
576
+ raise ValidationError(f"Invalid conversation_log format: {str(e)}")
471
577
 
472
- class PublicConversation(BaseModel):
578
+ def save(self, *args, **kwargs):
579
+ self.clean()
580
+ super().save(*args, **kwargs)
581
+
582
+ @property
583
+ def messages(self) -> List[ChatMessage]:
584
+ """Type-hinted accessor for conversation messages"""
585
+ validated_messages = []
586
+ for msg in self.conversation_log.get("chat", []):
587
+ try:
588
+ # Clean up inferred queries if they contain None
589
+ if msg.get("intent") and msg["intent"].get("inferred-queries"):
590
+ msg["intent"]["inferred-queries"] = [
591
+ q for q in msg["intent"]["inferred-queries"] if q is not None and isinstance(q, str)
592
+ ]
593
+ msg["message"] = str(msg.get("message", ""))
594
+ validated_messages.append(ChatMessage.model_validate(msg))
595
+ except ValidationError as e:
596
+ logger.warning(f"Skipping invalid message in conversation: {e}")
597
+ continue
598
+ return validated_messages
599
+
600
+
601
+ class PublicConversation(DbBaseModel):
473
602
  source_owner = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
474
603
  conversation_log = models.JSONField(default=dict)
475
604
  slug = models.CharField(max_length=200, default=None, null=True, blank=True)
@@ -499,12 +628,12 @@ def verify_public_conversation(sender, instance, **kwargs):
499
628
  instance.slug = slug
500
629
 
501
630
 
502
- class ReflectiveQuestion(BaseModel):
631
+ class ReflectiveQuestion(DbBaseModel):
503
632
  question = models.CharField(max_length=500)
504
633
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True)
505
634
 
506
635
 
507
- class Entry(BaseModel):
636
+ class Entry(DbBaseModel):
508
637
  class EntryType(models.TextChoices):
509
638
  IMAGE = "image"
510
639
  PDF = "pdf"
@@ -541,7 +670,7 @@ class Entry(BaseModel):
541
670
  raise ValidationError("An Entry cannot be associated with both a user and an agent.")
542
671
 
543
672
 
544
- class FileObject(BaseModel):
673
+ class FileObject(DbBaseModel):
545
674
  # Same as Entry but raw will be a much larger string
546
675
  file_name = models.CharField(max_length=400, default=None, null=True, blank=True)
547
676
  raw_text = models.TextField()
@@ -549,7 +678,7 @@ class FileObject(BaseModel):
549
678
  agent = models.ForeignKey(Agent, on_delete=models.CASCADE, default=None, null=True, blank=True)
550
679
 
551
680
 
552
- class EntryDates(BaseModel):
681
+ class EntryDates(DbBaseModel):
553
682
  date = models.DateField()
554
683
  entry = models.ForeignKey(Entry, on_delete=models.CASCADE, related_name="embeddings_dates")
555
684
 
@@ -559,12 +688,12 @@ class EntryDates(BaseModel):
559
688
  ]
560
689
 
561
690
 
562
- class UserRequests(BaseModel):
691
+ class UserRequests(DbBaseModel):
563
692
  user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
564
693
  slug = models.CharField(max_length=200)
565
694
 
566
695
 
567
- class DataStore(BaseModel):
696
+ class DataStore(DbBaseModel):
568
697
  key = models.CharField(max_length=200, unique=True)
569
698
  value = models.JSONField(default=dict)
570
699
  private = models.BooleanField(default=False)
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en" class="__variable_a693a0 __variable_702545"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/5455839c73f146e7-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/5984b96ba4822821-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/684adc3dde1b03f1-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/82e3b9a1bdaf0c26-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/8d1ea331386a0db8-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/b98b13dbc1c3b59c-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/e098aaaecc9cfbb2-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/css/bedf49fbfc598358.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/3c34171b174cc381.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-3a2dfd74acf6e193.js"/><script src="/_next/static/chunks/fd9d1056-2e6c8140e79afc3b.js" async=""></script><script src="/_next/static/chunks/7023-e8de2bded4df6539.js" async=""></script><script src="/_next/static/chunks/main-app-6d6ee3495efe03d4.js" async=""></script><meta name="robots" content="noindex"/><meta http-equiv="Content-Security-Policy" content="default-src &#x27;self&#x27; https://assets.khoj.dev; media-src * blob:; script-src &#x27;self&#x27; https://assets.khoj.dev &#x27;unsafe-inline&#x27; &#x27;unsafe-eval&#x27;; connect-src &#x27;self&#x27; blob: https://ipapi.co/json ws://localhost:42110; style-src &#x27;self&#x27; https://assets.khoj.dev &#x27;unsafe-inline&#x27; https://fonts.googleapis.com; img-src &#x27;self&#x27; data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com; font-src &#x27;self&#x27; https://assets.khoj.dev https://fonts.gstatic.com; child-src &#x27;none&#x27;; object-src &#x27;none&#x27;;"/><title>404: This page could not be found.</title><title>Khoj AI - Home</title><meta name="description" content="Your Second Brain."/><link rel="manifest" href="/static/khoj.webmanifest" crossorigin="use-credentials"/><meta property="og:title" content="Khoj AI"/><meta property="og:description" content="Your Second Brain."/><meta property="og:url" content="https://app.khoj.dev/"/><meta property="og:site_name" content="Khoj AI"/><meta property="og:image" content="https://assets.khoj.dev/khoj_lantern_256x256.png"/><meta property="og:image:width" content="256"/><meta property="og:image:height" content="256"/><meta property="og:image" content="https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png"/><meta property="og:image:width" content="1200"/><meta property="og:image:height" content="630"/><meta property="og:type" content="website"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:title" content="Khoj AI"/><meta name="twitter:description" content="Your Second Brain."/><meta name="twitter:image" content="https://assets.khoj.dev/khoj_lantern_256x256.png"/><meta name="twitter:image:width" content="256"/><meta name="twitter:image:height" content="256"/><meta name="twitter:image" content="https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png"/><meta name="twitter:image:width" content="1200"/><meta name="twitter:image:height" content="630"/><link rel="icon" href="/static/assets/icons/khoj_lantern.ico"/><link rel="apple-touch-icon" href="/static/assets/icons/khoj_lantern_256x256.png"/><meta name="next-size-adjust"/><script src="/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-3a2dfd74acf6e193.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/_next/static/media/5455839c73f146e7-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/_next/static/media/5984b96ba4822821-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n3:HL[\"/_next/static/media/684adc3dde1b03f1-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n4:HL[\"/_next/static/media/82e3b9a1bdaf0c26-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n5:HL[\"/_next/static/media/8d1ea331386a0db8-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n6:HL[\"/_next/static/media/b98b13dbc1c3b59c-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n7:HL[\"/_next/static/media/e098aaaecc9cfbb2-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n8:HL[\"/_next/static/css/bedf49fbfc598358.css\",\"style\"]\n9:HL[\"/_next/static/css/3c34171b174cc381.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"a:I[95751,[],\"\"]\nc:I[39275,[],\"\"]\nd:I[61343,[],\"\"]\n13:I[76130,[],\"\"]\ne:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\nf:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n10:{\"display\":\"inline-block\"}\n11:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\n14:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$La\",null,{\"buildId\":\"K_WyVARSz0loPVvwOW1gg\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\",\"\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$Lb\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$Lc\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Ld\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/bedf49fbfc598358.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/3c34171b174cc381.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"__variable_a693a0 __variable_702545\",\"children\":[[\"$\",\"meta\",null,{\"httpEquiv\":\"Content-Security-Policy\",\"content\":\"default-src 'self' https://assets.khoj.dev; media-src * blob:; script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval'; connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110; style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com; font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com; child-src 'none'; object-src 'none';\"}],[\"$\",\"body\",null,{\"children\":[\"$\",\"$Lc\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Ld\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$e\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$f\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$10\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$11\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$L12\"],\"globalErrorComponent\":\"$13\",\"missingSlots\":\"$W14\"}]\n"])</script><script>self.__next_f.push([1,"12:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"Khoj AI - Home\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Your Second Brain.\"}],[\"$\",\"link\",\"4\",{\"rel\":\"manifest\",\"href\":\"/static/khoj.webmanifest\",\"crossOrigin\":\"use-credentials\"}],[\"$\",\"meta\",\"5\",{\"property\":\"og:title\",\"content\":\"Khoj AI\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:description\",\"content\":\"Your Second Brain.\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:url\",\"content\":\"https://app.khoj.dev/\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:site_name\",\"content\":\"Khoj AI\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_256x256.png\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:image:width\",\"content\":\"256\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:image:height\",\"content\":\"256\"}],[\"$\",\"meta\",\"12\",{\"property\":\"og:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png\"}],[\"$\",\"meta\",\"13\",{\"property\":\"og:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"14\",{\"property\":\"og:image:height\",\"content\":\"630\"}],[\"$\",\"meta\",\"15\",{\"property\":\"og:type\",\"content\":\"website\"}],[\"$\",\"meta\",\"16\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"17\",{\"name\":\"twitter:title\",\"content\":\"Khoj AI\"}],[\"$\",\"meta\",\"18\",{\"name\":\"twitter:description\",\"content\":\"Your Second Brain.\"}],[\"$\",\"meta\",\"19\",{\"name\":\"twitter:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_256x256.png\"}],[\"$\",\"meta\",\"20\",{\"name\":\"twitter:image:width\",\"content\":\"256\"}],[\"$\",\"meta\",\"21\",{\"name\":\"twitter:image:height\",\"content\":\"256\"}],[\"$\",\"meta\",\"22\",{\"name\":\"twitter:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png\"}],[\"$\",\"meta\",\"23\",{\"name\":\"twitter:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"24\",{\"name\":\"twitter:image:height\",\"content\":\"630\"}],[\"$\",\"link\",\"25\",{\"rel\":\"icon\",\"href\":\"/static/assets/icons/khoj_lantern.ico\"}],[\"$\",\"link\",\"26\",{\"rel\":\"apple-touch-icon\",\"href\":\"/static/assets/icons/khoj_lantern_256x256.png\"}],[\"$\",\"meta\",\"27\",{\"name\":\"next-size-adjust\"}]]\n"])</script><script>self.__next_f.push([1,"b:null\n"])</script></body></html>
1
+ <!DOCTYPE html><html lang="en" class="__variable_f36179 __variable_702545"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/1d8a05b60287ae6c-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/77c207b095007c34-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/82ef96de0e8f4d8c-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/a6ecd16fa044d500-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/bd82c78e5b7b3fe9-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/c4250770ab8708b6-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/e098aaaecc9cfbb2-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/css/089de1d8526b96e9.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/3c34171b174cc381.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-5203c3872078c10c.js"/><script src="/_next/static/chunks/fd9d1056-2e6c8140e79afc3b.js" async=""></script><script src="/_next/static/chunks/7023-e8de2bded4df6539.js" async=""></script><script src="/_next/static/chunks/main-app-6d6ee3495efe03d4.js" async=""></script><meta name="robots" content="noindex"/><meta http-equiv="Content-Security-Policy" content="default-src &#x27;self&#x27; https://assets.khoj.dev; media-src * blob:; script-src &#x27;self&#x27; https://assets.khoj.dev https://app.chatwoot.com &#x27;unsafe-inline&#x27; &#x27;unsafe-eval&#x27;; connect-src &#x27;self&#x27; blob: https://ipapi.co/json ws://localhost:42110; style-src &#x27;self&#x27; https://assets.khoj.dev &#x27;unsafe-inline&#x27; https://fonts.googleapis.com; img-src &#x27;self&#x27; data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com; font-src &#x27;self&#x27; https://assets.khoj.dev https://fonts.gstatic.com; child-src &#x27;self&#x27; https://app.chatwoot.com; object-src &#x27;none&#x27;;"/><title>404: This page could not be found.</title><title>Khoj AI - Home</title><meta name="description" content="Your Second Brain."/><link rel="manifest" href="/static/khoj.webmanifest" crossorigin="use-credentials"/><meta property="og:title" content="Khoj AI"/><meta property="og:description" content="Your Second Brain."/><meta property="og:url" content="https://app.khoj.dev/"/><meta property="og:site_name" content="Khoj AI"/><meta property="og:image" content="https://assets.khoj.dev/khoj_lantern_256x256.png"/><meta property="og:image:width" content="256"/><meta property="og:image:height" content="256"/><meta property="og:image" content="https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png"/><meta property="og:image:width" content="1200"/><meta property="og:image:height" content="630"/><meta property="og:type" content="website"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:title" content="Khoj AI"/><meta name="twitter:description" content="Your Second Brain."/><meta name="twitter:image" content="https://assets.khoj.dev/khoj_lantern_256x256.png"/><meta name="twitter:image:width" content="256"/><meta name="twitter:image:height" content="256"/><meta name="twitter:image" content="https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png"/><meta name="twitter:image:width" content="1200"/><meta name="twitter:image:height" content="630"/><link rel="icon" href="/static/assets/icons/khoj_lantern.ico"/><link rel="apple-touch-icon" href="/static/assets/icons/khoj_lantern_256x256.png"/><meta name="next-size-adjust"/><script src="/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-5203c3872078c10c.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/_next/static/media/1d8a05b60287ae6c-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/_next/static/media/77c207b095007c34-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n3:HL[\"/_next/static/media/82ef96de0e8f4d8c-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n4:HL[\"/_next/static/media/a6ecd16fa044d500-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n5:HL[\"/_next/static/media/bd82c78e5b7b3fe9-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n6:HL[\"/_next/static/media/c4250770ab8708b6-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n7:HL[\"/_next/static/media/e098aaaecc9cfbb2-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n8:HL[\"/_next/static/css/089de1d8526b96e9.css\",\"style\"]\n9:HL[\"/_next/static/css/3c34171b174cc381.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"a:I[95751,[],\"\"]\nc:I[39275,[],\"\"]\nd:I[61343,[],\"\"]\n13:I[76130,[],\"\"]\ne:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\nf:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n10:{\"display\":\"inline-block\"}\n11:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\n14:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$La\",null,{\"buildId\":\"J7Vqh1vjCleYuVLeTaJL6\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\",\"\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$Lb\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$Lc\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Ld\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/089de1d8526b96e9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/3c34171b174cc381.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"__variable_f36179 __variable_702545\",\"children\":[[\"$\",\"meta\",null,{\"httpEquiv\":\"Content-Security-Policy\",\"content\":\"default-src 'self' https://assets.khoj.dev; media-src * blob:; script-src 'self' https://assets.khoj.dev https://app.chatwoot.com 'unsafe-inline' 'unsafe-eval'; connect-src 'self' blob: https://ipapi.co/json ws://localhost:42110; style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://*.khoj.dev https://*.googleusercontent.com https://*.google.com/ https://*.gstatic.com; font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com; child-src 'self' https://app.chatwoot.com; object-src 'none';\"}],[\"$\",\"body\",null,{\"children\":[\"$\",\"$Lc\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$Ld\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$e\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$f\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$10\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$11\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$L12\"],\"globalErrorComponent\":\"$13\",\"missingSlots\":\"$W14\"}]\n"])</script><script>self.__next_f.push([1,"12:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"Khoj AI - Home\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Your Second Brain.\"}],[\"$\",\"link\",\"4\",{\"rel\":\"manifest\",\"href\":\"/static/khoj.webmanifest\",\"crossOrigin\":\"use-credentials\"}],[\"$\",\"meta\",\"5\",{\"property\":\"og:title\",\"content\":\"Khoj AI\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:description\",\"content\":\"Your Second Brain.\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:url\",\"content\":\"https://app.khoj.dev/\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:site_name\",\"content\":\"Khoj AI\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_256x256.png\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:image:width\",\"content\":\"256\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:image:height\",\"content\":\"256\"}],[\"$\",\"meta\",\"12\",{\"property\":\"og:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png\"}],[\"$\",\"meta\",\"13\",{\"property\":\"og:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"14\",{\"property\":\"og:image:height\",\"content\":\"630\"}],[\"$\",\"meta\",\"15\",{\"property\":\"og:type\",\"content\":\"website\"}],[\"$\",\"meta\",\"16\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"17\",{\"name\":\"twitter:title\",\"content\":\"Khoj AI\"}],[\"$\",\"meta\",\"18\",{\"name\":\"twitter:description\",\"content\":\"Your Second Brain.\"}],[\"$\",\"meta\",\"19\",{\"name\":\"twitter:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_256x256.png\"}],[\"$\",\"meta\",\"20\",{\"name\":\"twitter:image:width\",\"content\":\"256\"}],[\"$\",\"meta\",\"21\",{\"name\":\"twitter:image:height\",\"content\":\"256\"}],[\"$\",\"meta\",\"22\",{\"name\":\"twitter:image\",\"content\":\"https://assets.khoj.dev/khoj_lantern_logomarktype_1200x630.png\"}],[\"$\",\"meta\",\"23\",{\"name\":\"twitter:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"24\",{\"name\":\"twitter:image:height\",\"content\":\"630\"}],[\"$\",\"link\",\"25\",{\"rel\":\"icon\",\"href\":\"/static/assets/icons/khoj_lantern.ico\"}],[\"$\",\"link\",\"26\",{\"rel\":\"apple-touch-icon\",\"href\":\"/static/assets/icons/khoj_lantern_256x256.png\"}],[\"$\",\"meta\",\"27\",{\"name\":\"next-size-adjust\"}]]\n"])</script><script>self.__next_f.push([1,"b:null\n"])</script></body></html>