khoj 1.28.4.dev23__py3-none-any.whl → 1.28.4.dev71__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 (65) hide show
  1. khoj/database/adapters/__init__.py +4 -0
  2. khoj/database/models/__init__.py +4 -0
  3. khoj/interface/compiled/404/index.html +1 -1
  4. khoj/interface/compiled/_next/static/chunks/1603-2418b11d8e8dacb9.js +1 -0
  5. khoj/interface/compiled/_next/static/chunks/3124-a4cea2eda163128d.js +1 -0
  6. khoj/interface/compiled/_next/static/chunks/5538-5c4f2271e9377b74.js +1 -0
  7. khoj/interface/compiled/_next/static/chunks/8423-a87e3671c4217ab6.js +1 -0
  8. khoj/interface/compiled/_next/static/chunks/9417-7a8a6da918d37750.js +1 -0
  9. khoj/interface/compiled/_next/static/chunks/app/agents/{page-36da67f03a173e52.js → page-ee4f0da14df15091.js} +1 -1
  10. khoj/interface/compiled/_next/static/chunks/app/automations/{page-774ae3e033f938cd.js → page-da59a2b9ec07da16.js} +1 -1
  11. khoj/interface/compiled/_next/static/chunks/app/chat/page-04313ed6d8f38904.js +1 -0
  12. khoj/interface/compiled/_next/static/chunks/app/{page-322c37514a3a613a.js → page-5c06dadacb1b5945.js} +1 -1
  13. khoj/interface/compiled/_next/static/chunks/app/search/{page-9b64f61caa5bd7f9.js → page-4f44549ba3807021.js} +1 -1
  14. khoj/interface/compiled/_next/static/chunks/app/settings/page-88dbd5c184dcd1e3.js +1 -0
  15. khoj/interface/compiled/_next/static/chunks/app/share/chat/page-9257e8817dcd6af3.js +1 -0
  16. khoj/interface/compiled/_next/static/css/{9d45de78fba367c1.css → 2ff098d0815fdbc1.css} +1 -1
  17. khoj/interface/compiled/_next/static/css/af0f36f71f368260.css +25 -0
  18. khoj/interface/compiled/agents/index.html +1 -1
  19. khoj/interface/compiled/agents/index.txt +2 -2
  20. khoj/interface/compiled/automations/index.html +1 -1
  21. khoj/interface/compiled/automations/index.txt +2 -2
  22. khoj/interface/compiled/chat/index.html +1 -1
  23. khoj/interface/compiled/chat/index.txt +2 -2
  24. khoj/interface/compiled/index.html +1 -1
  25. khoj/interface/compiled/index.txt +2 -2
  26. khoj/interface/compiled/search/index.html +1 -1
  27. khoj/interface/compiled/search/index.txt +2 -2
  28. khoj/interface/compiled/settings/index.html +1 -1
  29. khoj/interface/compiled/settings/index.txt +2 -2
  30. khoj/interface/compiled/share/chat/index.html +1 -1
  31. khoj/interface/compiled/share/chat/index.txt +2 -2
  32. khoj/processor/content/docx/docx_to_entries.py +25 -19
  33. khoj/processor/content/pdf/pdf_to_entries.py +34 -26
  34. khoj/processor/conversation/anthropic/anthropic_chat.py +7 -1
  35. khoj/processor/conversation/google/gemini_chat.py +15 -2
  36. khoj/processor/conversation/offline/chat_model.py +4 -0
  37. khoj/processor/conversation/openai/gpt.py +6 -1
  38. khoj/processor/conversation/prompts.py +15 -4
  39. khoj/processor/conversation/utils.py +69 -11
  40. khoj/processor/image/generate.py +2 -0
  41. khoj/processor/tools/online_search.py +19 -3
  42. khoj/processor/tools/run_code.py +4 -0
  43. khoj/routers/api.py +5 -0
  44. khoj/routers/api_chat.py +66 -13
  45. khoj/routers/api_content.py +78 -6
  46. khoj/routers/helpers.py +98 -31
  47. khoj/routers/research.py +9 -2
  48. khoj/utils/rawconfig.py +32 -0
  49. {khoj-1.28.4.dev23.dist-info → khoj-1.28.4.dev71.dist-info}/METADATA +1 -1
  50. {khoj-1.28.4.dev23.dist-info → khoj-1.28.4.dev71.dist-info}/RECORD +56 -56
  51. khoj/interface/compiled/_next/static/chunks/1603-c1568f45947e9f2c.js +0 -1
  52. khoj/interface/compiled/_next/static/chunks/5538-bf582517a8dd3faa.js +0 -1
  53. khoj/interface/compiled/_next/static/chunks/8423-a1f432e4a8d9a6b0.js +0 -1
  54. khoj/interface/compiled/_next/static/chunks/8840-b8d7b9f0923c6651.js +0 -1
  55. khoj/interface/compiled/_next/static/chunks/9417-0d0fc7eb49a86abb.js +0 -1
  56. khoj/interface/compiled/_next/static/chunks/app/chat/page-a369e2bda9897794.js +0 -1
  57. khoj/interface/compiled/_next/static/chunks/app/settings/page-10b288c103f19468.js +0 -1
  58. khoj/interface/compiled/_next/static/chunks/app/share/chat/page-959d5f097cf38c93.js +0 -1
  59. khoj/interface/compiled/_next/static/css/d2bc549245313f26.css +0 -25
  60. /khoj/interface/compiled/_next/static/{s_mKS5kELaw2v4a7_yWNP → I1jjXZh1lBQiY837mKXbn}/_buildManifest.js +0 -0
  61. /khoj/interface/compiled/_next/static/{s_mKS5kELaw2v4a7_yWNP → I1jjXZh1lBQiY837mKXbn}/_ssgManifest.js +0 -0
  62. /khoj/interface/compiled/_next/static/chunks/{1970-d44050bf658ae5cc.js → 1970-30985763f1451fa2.js} +0 -0
  63. {khoj-1.28.4.dev23.dist-info → khoj-1.28.4.dev71.dist-info}/WHEEL +0 -0
  64. {khoj-1.28.4.dev23.dist-info → khoj-1.28.4.dev71.dist-info}/entry_points.txt +0 -0
  65. {khoj-1.28.4.dev23.dist-info → khoj-1.28.4.dev71.dist-info}/licenses/LICENSE +0 -0
khoj/routers/helpers.py CHANGED
@@ -105,6 +105,7 @@ from khoj.utils.config import OfflineChatProcessorModel
105
105
  from khoj.utils.helpers import (
106
106
  LRU,
107
107
  ConversationCommand,
108
+ get_file_type,
108
109
  is_none_or_empty,
109
110
  is_valid_url,
110
111
  log_telemetry,
@@ -112,7 +113,7 @@ from khoj.utils.helpers import (
112
113
  timer,
113
114
  tool_descriptions_for_llm,
114
115
  )
115
- from khoj.utils.rawconfig import LocationData
116
+ from khoj.utils.rawconfig import ChatRequestBody, FileAttachment, FileData, LocationData
116
117
 
117
118
  logger = logging.getLogger(__name__)
118
119
 
@@ -168,6 +169,12 @@ async def is_ready_to_chat(user: KhojUser):
168
169
  raise HTTPException(status_code=500, detail="Set your OpenAI API key or enable Local LLM via Khoj settings.")
169
170
 
170
171
 
172
+ def get_file_content(file: UploadFile):
173
+ file_content = file.file.read()
174
+ file_type, encoding = get_file_type(file.content_type, file_content)
175
+ return FileData(name=file.filename, content=file_content, file_type=file_type, encoding=encoding)
176
+
177
+
171
178
  def update_telemetry_state(
172
179
  request: Request,
173
180
  telemetry_type: str,
@@ -249,6 +256,39 @@ async def agenerate_chat_response(*args):
249
256
  return await loop.run_in_executor(executor, generate_chat_response, *args)
250
257
 
251
258
 
259
+ def gather_raw_query_files(
260
+ query_files: Dict[str, str],
261
+ ):
262
+ """
263
+ Gather contextual data from the given (raw) files
264
+ """
265
+
266
+ if len(query_files) == 0:
267
+ return ""
268
+
269
+ contextual_data = " ".join(
270
+ [f"File: {file_name}\n\n{file_content}\n\n" for file_name, file_content in query_files.items()]
271
+ )
272
+ return f"I have attached the following files:\n\n{contextual_data}"
273
+
274
+
275
+ async def acreate_title_from_history(
276
+ user: KhojUser,
277
+ conversation: Conversation,
278
+ ):
279
+ """
280
+ Create a title from the given conversation history
281
+ """
282
+ chat_history = construct_chat_history(conversation.conversation_log)
283
+
284
+ title_generation_prompt = prompts.conversation_title_generation.format(chat_history=chat_history)
285
+
286
+ with timer("Chat actor: Generate title from conversation history", logger):
287
+ response = await send_message_to_model_wrapper(title_generation_prompt, user=user)
288
+
289
+ return response.strip()
290
+
291
+
252
292
  async def acreate_title_from_query(query: str, user: KhojUser = None) -> str:
253
293
  """
254
294
  Create a title from the given query
@@ -294,6 +334,7 @@ async def aget_relevant_information_sources(
294
334
  user: KhojUser,
295
335
  query_images: List[str] = None,
296
336
  agent: Agent = None,
337
+ query_files: str = None,
297
338
  tracer: dict = {},
298
339
  ):
299
340
  """
@@ -331,6 +372,7 @@ async def aget_relevant_information_sources(
331
372
  relevant_tools_prompt,
332
373
  response_type="json_object",
333
374
  user=user,
375
+ query_files=query_files,
334
376
  tracer=tracer,
335
377
  )
336
378
 
@@ -440,6 +482,7 @@ async def infer_webpage_urls(
440
482
  user: KhojUser,
441
483
  query_images: List[str] = None,
442
484
  agent: Agent = None,
485
+ query_files: str = None,
443
486
  tracer: dict = {},
444
487
  ) -> List[str]:
445
488
  """
@@ -469,6 +512,7 @@ async def infer_webpage_urls(
469
512
  query_images=query_images,
470
513
  response_type="json_object",
471
514
  user=user,
515
+ query_files=query_files,
472
516
  tracer=tracer,
473
517
  )
474
518
 
@@ -494,6 +538,7 @@ async def generate_online_subqueries(
494
538
  user: KhojUser,
495
539
  query_images: List[str] = None,
496
540
  agent: Agent = None,
541
+ query_files: str = None,
497
542
  tracer: dict = {},
498
543
  ) -> Set[str]:
499
544
  """
@@ -523,6 +568,7 @@ async def generate_online_subqueries(
523
568
  query_images=query_images,
524
569
  response_type="json_object",
525
570
  user=user,
571
+ query_files=query_files,
526
572
  tracer=tracer,
527
573
  )
528
574
 
@@ -645,26 +691,38 @@ async def generate_summary_from_files(
645
691
  query_images: List[str] = None,
646
692
  agent: Agent = None,
647
693
  send_status_func: Optional[Callable] = None,
694
+ query_files: str = None,
648
695
  tracer: dict = {},
649
696
  ):
650
697
  try:
651
- file_object = None
698
+ file_objects = None
652
699
  if await EntryAdapters.aagent_has_entries(agent):
653
700
  file_names = await EntryAdapters.aget_agent_entry_filepaths(agent)
654
701
  if len(file_names) > 0:
655
- file_object = await FileObjectAdapters.async_get_file_objects_by_name(None, file_names.pop(), agent)
656
-
657
- if len(file_filters) > 0:
658
- file_object = await FileObjectAdapters.async_get_file_objects_by_name(user, file_filters[0])
702
+ file_objects = await FileObjectAdapters.async_get_file_objects_by_name(None, file_names.pop(), agent)
659
703
 
660
- if len(file_object) == 0:
661
- response_log = "Sorry, I couldn't find the full text of this file."
704
+ if (file_objects and len(file_objects) == 0 and not query_files) or (not file_objects and not query_files):
705
+ response_log = "Sorry, I couldn't find anything to summarize."
662
706
  yield response_log
663
707
  return
664
- contextual_data = " ".join([file.raw_text for file in file_object])
708
+
709
+ contextual_data = " ".join([f"File: {file.file_name}\n\n{file.raw_text}" for file in file_objects])
710
+
711
+ if query_files:
712
+ contextual_data += f"\n\n{query_files}"
713
+
665
714
  if not q:
666
715
  q = "Create a general summary of the file"
667
- async for result in send_status_func(f"**Constructing Summary Using:** {file_object[0].file_name}"):
716
+
717
+ file_names = [file.file_name for file in file_objects]
718
+ file_names.extend(file_filters)
719
+
720
+ all_file_names = ""
721
+
722
+ for file_name in file_names:
723
+ all_file_names += f"- {file_name}\n"
724
+
725
+ async for result in send_status_func(f"**Constructing Summary Using:**\n{all_file_names}"):
668
726
  yield {ChatEvent.STATUS: result}
669
727
 
670
728
  response = await extract_relevant_summary(
@@ -694,6 +752,7 @@ async def generate_excalidraw_diagram(
694
752
  user: KhojUser = None,
695
753
  agent: Agent = None,
696
754
  send_status_func: Optional[Callable] = None,
755
+ query_files: str = None,
697
756
  tracer: dict = {},
698
757
  ):
699
758
  if send_status_func:
@@ -709,6 +768,7 @@ async def generate_excalidraw_diagram(
709
768
  query_images=query_images,
710
769
  user=user,
711
770
  agent=agent,
771
+ query_files=query_files,
712
772
  tracer=tracer,
713
773
  )
714
774
 
@@ -735,6 +795,7 @@ async def generate_better_diagram_description(
735
795
  query_images: List[str] = None,
736
796
  user: KhojUser = None,
737
797
  agent: Agent = None,
798
+ query_files: str = None,
738
799
  tracer: dict = {},
739
800
  ) -> str:
740
801
  """
@@ -773,7 +834,11 @@ async def generate_better_diagram_description(
773
834
 
774
835
  with timer("Chat actor: Generate better diagram description", logger):
775
836
  response = await send_message_to_model_wrapper(
776
- improve_diagram_description_prompt, query_images=query_images, user=user, tracer=tracer
837
+ improve_diagram_description_prompt,
838
+ query_images=query_images,
839
+ user=user,
840
+ query_files=query_files,
841
+ tracer=tracer,
777
842
  )
778
843
  response = response.strip()
779
844
  if response.startswith(('"', "'")) and response.endswith(('"', "'")):
@@ -820,6 +885,7 @@ async def generate_better_image_prompt(
820
885
  query_images: Optional[List[str]] = None,
821
886
  user: KhojUser = None,
822
887
  agent: Agent = None,
888
+ query_files: str = "",
823
889
  tracer: dict = {},
824
890
  ) -> str:
825
891
  """
@@ -868,7 +934,7 @@ async def generate_better_image_prompt(
868
934
 
869
935
  with timer("Chat actor: Generate contextual image prompt", logger):
870
936
  response = await send_message_to_model_wrapper(
871
- image_prompt, query_images=query_images, user=user, tracer=tracer
937
+ image_prompt, query_images=query_images, user=user, query_files=query_files, tracer=tracer
872
938
  )
873
939
  response = response.strip()
874
940
  if response.startswith(('"', "'")) and response.endswith(('"', "'")):
@@ -884,6 +950,7 @@ async def send_message_to_model_wrapper(
884
950
  user: KhojUser = None,
885
951
  query_images: List[str] = None,
886
952
  context: str = "",
953
+ query_files: str = None,
887
954
  tracer: dict = {},
888
955
  ):
889
956
  conversation_config: ChatModelOptions = await ConversationAdapters.aget_default_conversation_config(user)
@@ -923,6 +990,7 @@ async def send_message_to_model_wrapper(
923
990
  max_prompt_size=max_tokens,
924
991
  vision_enabled=vision_available,
925
992
  model_type=conversation_config.model_type,
993
+ query_files=query_files,
926
994
  )
927
995
 
928
996
  return send_message_to_model_offline(
@@ -949,6 +1017,7 @@ async def send_message_to_model_wrapper(
949
1017
  vision_enabled=vision_available,
950
1018
  query_images=query_images,
951
1019
  model_type=conversation_config.model_type,
1020
+ query_files=query_files,
952
1021
  )
953
1022
 
954
1023
  return send_message_to_model(
@@ -971,6 +1040,7 @@ async def send_message_to_model_wrapper(
971
1040
  vision_enabled=vision_available,
972
1041
  query_images=query_images,
973
1042
  model_type=conversation_config.model_type,
1043
+ query_files=query_files,
974
1044
  )
975
1045
 
976
1046
  return anthropic_send_message_to_model(
@@ -992,6 +1062,7 @@ async def send_message_to_model_wrapper(
992
1062
  vision_enabled=vision_available,
993
1063
  query_images=query_images,
994
1064
  model_type=conversation_config.model_type,
1065
+ query_files=query_files,
995
1066
  )
996
1067
 
997
1068
  return gemini_send_message_to_model(
@@ -1006,6 +1077,7 @@ def send_message_to_model_wrapper_sync(
1006
1077
  system_message: str = "",
1007
1078
  response_type: str = "text",
1008
1079
  user: KhojUser = None,
1080
+ query_files: str = "",
1009
1081
  tracer: dict = {},
1010
1082
  ):
1011
1083
  conversation_config: ChatModelOptions = ConversationAdapters.get_default_conversation_config(user)
@@ -1030,6 +1102,7 @@ def send_message_to_model_wrapper_sync(
1030
1102
  max_prompt_size=max_tokens,
1031
1103
  vision_enabled=vision_available,
1032
1104
  model_type=conversation_config.model_type,
1105
+ query_files=query_files,
1033
1106
  )
1034
1107
 
1035
1108
  return send_message_to_model_offline(
@@ -1051,6 +1124,7 @@ def send_message_to_model_wrapper_sync(
1051
1124
  max_prompt_size=max_tokens,
1052
1125
  vision_enabled=vision_available,
1053
1126
  model_type=conversation_config.model_type,
1127
+ query_files=query_files,
1054
1128
  )
1055
1129
 
1056
1130
  openai_response = send_message_to_model(
@@ -1072,6 +1146,7 @@ def send_message_to_model_wrapper_sync(
1072
1146
  max_prompt_size=max_tokens,
1073
1147
  vision_enabled=vision_available,
1074
1148
  model_type=conversation_config.model_type,
1149
+ query_files=query_files,
1075
1150
  )
1076
1151
 
1077
1152
  return anthropic_send_message_to_model(
@@ -1091,6 +1166,7 @@ def send_message_to_model_wrapper_sync(
1091
1166
  max_prompt_size=max_tokens,
1092
1167
  vision_enabled=vision_available,
1093
1168
  model_type=conversation_config.model_type,
1169
+ query_files=query_files,
1094
1170
  )
1095
1171
 
1096
1172
  return gemini_send_message_to_model(
@@ -1120,8 +1196,10 @@ def generate_chat_response(
1120
1196
  user_name: Optional[str] = None,
1121
1197
  meta_research: str = "",
1122
1198
  query_images: Optional[List[str]] = None,
1123
- tracer: dict = {},
1124
1199
  train_of_thought: List[Any] = [],
1200
+ query_files: str = None,
1201
+ raw_query_files: List[FileAttachment] = None,
1202
+ tracer: dict = {},
1125
1203
  ) -> Tuple[Union[ThreadedGenerator, Iterator[str]], Dict[str, str]]:
1126
1204
  # Initialize Variables
1127
1205
  chat_response = None
@@ -1142,8 +1220,9 @@ def generate_chat_response(
1142
1220
  client_application=client_application,
1143
1221
  conversation_id=conversation_id,
1144
1222
  query_images=query_images,
1145
- tracer=tracer,
1146
1223
  train_of_thought=train_of_thought,
1224
+ raw_query_files=raw_query_files,
1225
+ tracer=tracer,
1147
1226
  )
1148
1227
 
1149
1228
  query_to_run = q
@@ -1177,6 +1256,7 @@ def generate_chat_response(
1177
1256
  location_data=location_data,
1178
1257
  user_name=user_name,
1179
1258
  agent=agent,
1259
+ query_files=query_files,
1180
1260
  tracer=tracer,
1181
1261
  )
1182
1262
 
@@ -1202,6 +1282,7 @@ def generate_chat_response(
1202
1282
  user_name=user_name,
1203
1283
  agent=agent,
1204
1284
  vision_available=vision_available,
1285
+ query_files=query_files,
1205
1286
  tracer=tracer,
1206
1287
  )
1207
1288
 
@@ -1224,6 +1305,7 @@ def generate_chat_response(
1224
1305
  user_name=user_name,
1225
1306
  agent=agent,
1226
1307
  vision_available=vision_available,
1308
+ query_files=query_files,
1227
1309
  tracer=tracer,
1228
1310
  )
1229
1311
  elif conversation_config.model_type == ChatModelOptions.ModelType.GOOGLE:
@@ -1243,7 +1325,9 @@ def generate_chat_response(
1243
1325
  location_data=location_data,
1244
1326
  user_name=user_name,
1245
1327
  agent=agent,
1328
+ query_images=query_images,
1246
1329
  vision_available=vision_available,
1330
+ query_files=query_files,
1247
1331
  tracer=tracer,
1248
1332
  )
1249
1333
 
@@ -1256,23 +1340,6 @@ def generate_chat_response(
1256
1340
  return chat_response, metadata
1257
1341
 
1258
1342
 
1259
- class ChatRequestBody(BaseModel):
1260
- q: str
1261
- n: Optional[int] = 7
1262
- d: Optional[float] = None
1263
- stream: Optional[bool] = False
1264
- title: Optional[str] = None
1265
- conversation_id: Optional[str] = None
1266
- turn_id: Optional[str] = None
1267
- city: Optional[str] = None
1268
- region: Optional[str] = None
1269
- country: Optional[str] = None
1270
- country_code: Optional[str] = None
1271
- timezone: Optional[str] = None
1272
- images: Optional[list[str]] = None
1273
- create_new: Optional[bool] = False
1274
-
1275
-
1276
1343
  class DeleteMessageRequestBody(BaseModel):
1277
1344
  conversation_id: str
1278
1345
  turn_id: str
khoj/routers/research.py CHANGED
@@ -11,6 +11,7 @@ from khoj.processor.conversation import prompts
11
11
  from khoj.processor.conversation.utils import (
12
12
  InformationCollectionIteration,
13
13
  clean_json,
14
+ construct_chat_history,
14
15
  construct_iteration_history,
15
16
  construct_tool_chat_history,
16
17
  )
@@ -19,8 +20,6 @@ from khoj.processor.tools.run_code import run_code
19
20
  from khoj.routers.api import extract_references_and_questions
20
21
  from khoj.routers.helpers import (
21
22
  ChatEvent,
22
- construct_chat_history,
23
- extract_relevant_info,
24
23
  generate_summary_from_files,
25
24
  send_message_to_model_wrapper,
26
25
  )
@@ -47,6 +46,7 @@ async def apick_next_tool(
47
46
  max_iterations: int = 5,
48
47
  send_status_func: Optional[Callable] = None,
49
48
  tracer: dict = {},
49
+ query_files: str = None,
50
50
  ):
51
51
  """Given a query, determine which of the available tools the agent should use in order to answer appropriately."""
52
52
 
@@ -92,6 +92,7 @@ async def apick_next_tool(
92
92
  response_type="json_object",
93
93
  user=user,
94
94
  query_images=query_images,
95
+ query_files=query_files,
95
96
  tracer=tracer,
96
97
  )
97
98
  except Exception as e:
@@ -151,6 +152,7 @@ async def execute_information_collection(
151
152
  location: LocationData = None,
152
153
  file_filters: List[str] = [],
153
154
  tracer: dict = {},
155
+ query_files: str = None,
154
156
  ):
155
157
  current_iteration = 0
156
158
  MAX_ITERATIONS = 5
@@ -174,6 +176,7 @@ async def execute_information_collection(
174
176
  MAX_ITERATIONS,
175
177
  send_status_func,
176
178
  tracer=tracer,
179
+ query_files=query_files,
177
180
  ):
178
181
  if isinstance(result, dict) and ChatEvent.STATUS in result:
179
182
  yield result[ChatEvent.STATUS]
@@ -204,6 +207,7 @@ async def execute_information_collection(
204
207
  previous_inferred_queries=previous_inferred_queries,
205
208
  agent=agent,
206
209
  tracer=tracer,
210
+ query_files=query_files,
207
211
  ):
208
212
  if isinstance(result, dict) and ChatEvent.STATUS in result:
209
213
  yield result[ChatEvent.STATUS]
@@ -265,6 +269,7 @@ async def execute_information_collection(
265
269
  query_images=query_images,
266
270
  agent=agent,
267
271
  tracer=tracer,
272
+ query_files=query_files,
268
273
  ):
269
274
  if isinstance(result, dict) and ChatEvent.STATUS in result:
270
275
  yield result[ChatEvent.STATUS]
@@ -295,6 +300,7 @@ async def execute_information_collection(
295
300
  send_status_func,
296
301
  query_images=query_images,
297
302
  agent=agent,
303
+ query_files=query_files,
298
304
  tracer=tracer,
299
305
  ):
300
306
  if isinstance(result, dict) and ChatEvent.STATUS in result:
@@ -320,6 +326,7 @@ async def execute_information_collection(
320
326
  query_images=query_images,
321
327
  agent=agent,
322
328
  send_status_func=send_status_func,
329
+ query_files=query_files,
323
330
  ):
324
331
  if isinstance(result, dict) and ChatEvent.STATUS in result:
325
332
  yield result[ChatEvent.STATUS]
khoj/utils/rawconfig.py CHANGED
@@ -138,6 +138,38 @@ class SearchResponse(ConfigBase):
138
138
  corpus_id: str
139
139
 
140
140
 
141
+ class FileData(BaseModel):
142
+ name: str
143
+ content: bytes
144
+ file_type: str
145
+ encoding: str | None = None
146
+
147
+
148
+ class FileAttachment(BaseModel):
149
+ name: str
150
+ content: str
151
+ file_type: str
152
+ size: int
153
+
154
+
155
+ class ChatRequestBody(BaseModel):
156
+ q: str
157
+ n: Optional[int] = 7
158
+ d: Optional[float] = None
159
+ stream: Optional[bool] = False
160
+ title: Optional[str] = None
161
+ conversation_id: Optional[str] = None
162
+ turn_id: Optional[str] = None
163
+ city: Optional[str] = None
164
+ region: Optional[str] = None
165
+ country: Optional[str] = None
166
+ country_code: Optional[str] = None
167
+ timezone: Optional[str] = None
168
+ images: Optional[list[str]] = None
169
+ files: Optional[list[FileAttachment]] = []
170
+ create_new: Optional[bool] = False
171
+
172
+
141
173
  class Entry:
142
174
  raw: str
143
175
  compiled: str
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: khoj
3
- Version: 1.28.4.dev23
3
+ Version: 1.28.4.dev71
4
4
  Summary: Your Second Brain
5
5
  Project-URL: Homepage, https://khoj.dev
6
6
  Project-URL: Documentation, https://docs.khoj.dev