khoj 2.0.0b9.dev11__py3-none-any.whl → 2.0.0b11.dev9__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 (30) hide show
  1. khoj/interface/compiled/404/index.html +2 -2
  2. khoj/interface/compiled/_next/static/chunks/{webpack-4b00e5a0da4a9dae.js → webpack-92606a2523b656a3.js} +1 -1
  3. khoj/interface/compiled/_next/static/css/{4398afc6d5a37666.css → 93eeacc43e261162.css} +1 -1
  4. khoj/interface/compiled/agents/index.html +2 -2
  5. khoj/interface/compiled/agents/index.txt +1 -1
  6. khoj/interface/compiled/automations/index.html +2 -2
  7. khoj/interface/compiled/automations/index.txt +1 -1
  8. khoj/interface/compiled/chat/index.html +2 -2
  9. khoj/interface/compiled/chat/index.txt +1 -1
  10. khoj/interface/compiled/index.html +2 -2
  11. khoj/interface/compiled/index.txt +1 -1
  12. khoj/interface/compiled/search/index.html +2 -2
  13. khoj/interface/compiled/search/index.txt +1 -1
  14. khoj/interface/compiled/settings/index.html +2 -2
  15. khoj/interface/compiled/settings/index.txt +1 -1
  16. khoj/interface/compiled/share/chat/index.html +2 -2
  17. khoj/interface/compiled/share/chat/index.txt +1 -1
  18. khoj/processor/conversation/openai/utils.py +54 -39
  19. khoj/processor/conversation/utils.py +1 -0
  20. khoj/processor/operator/__init__.py +1 -1
  21. khoj/routers/api_chat.py +97 -22
  22. khoj/routers/helpers.py +7 -7
  23. khoj/routers/research.py +1 -1
  24. {khoj-2.0.0b9.dev11.dist-info → khoj-2.0.0b11.dev9.dist-info}/METADATA +1 -1
  25. {khoj-2.0.0b9.dev11.dist-info → khoj-2.0.0b11.dev9.dist-info}/RECORD +30 -30
  26. /khoj/interface/compiled/_next/static/{M8PL43caF5dQgNQPB6Hd7 → JybcBQEMXcv7ZKN1xxi5F}/_buildManifest.js +0 -0
  27. /khoj/interface/compiled/_next/static/{M8PL43caF5dQgNQPB6Hd7 → JybcBQEMXcv7ZKN1xxi5F}/_ssgManifest.js +0 -0
  28. {khoj-2.0.0b9.dev11.dist-info → khoj-2.0.0b11.dev9.dist-info}/WHEEL +0 -0
  29. {khoj-2.0.0b9.dev11.dist-info → khoj-2.0.0b11.dev9.dist-info}/entry_points.txt +0 -0
  30. {khoj-2.0.0b9.dev11.dist-info → khoj-2.0.0b11.dev9.dist-info}/licenses/LICENSE +0 -0
khoj/routers/api_chat.py CHANGED
@@ -4,6 +4,7 @@ import json
4
4
  import logging
5
5
  import time
6
6
  import uuid
7
+ from dataclasses import dataclass
7
8
  from datetime import datetime
8
9
  from functools import partial
9
10
  from typing import Any, Dict, List, Optional
@@ -703,7 +704,6 @@ async def event_generator(
703
704
  train_of_thought = []
704
705
  cancellation_event = asyncio.Event()
705
706
  child_interrupt_queue: asyncio.Queue = asyncio.Queue(maxsize=10)
706
- event_delimiter = "␃🔚␗"
707
707
 
708
708
  tracer: dict = {
709
709
  "mid": turn_id,
@@ -790,7 +790,7 @@ async def event_generator(
790
790
 
791
791
  # Check if any interrupt query is received
792
792
  if interrupt_query := get_message_from_queue(parent_interrupt_queue):
793
- if interrupt_query == event_delimiter:
793
+ if interrupt_query == ChatEvent.END_EVENT.value:
794
794
  cancellation_event.set()
795
795
  logger.debug(f"Chat cancelled by user {user} via interrupt queue.")
796
796
  else:
@@ -871,7 +871,7 @@ async def event_generator(
871
871
  )
872
872
  finally:
873
873
  if not cancellation_event.is_set():
874
- yield event_delimiter
874
+ yield ChatEvent.END_EVENT.value
875
875
  # Cancel the disconnect monitor task if it is still running
876
876
  if cancellation_event.is_set() or event_type == ChatEvent.END_RESPONSE:
877
877
  await cancel_disconnect_monitor()
@@ -1043,7 +1043,7 @@ async def event_generator(
1043
1043
  tracer=tracer,
1044
1044
  cancellation_event=cancellation_event,
1045
1045
  interrupt_queue=child_interrupt_queue,
1046
- abort_message=event_delimiter,
1046
+ abort_message=ChatEvent.END_EVENT.value,
1047
1047
  ):
1048
1048
  if isinstance(research_result, ResearchIteration):
1049
1049
  if research_result.summarizedResult:
@@ -1397,6 +1397,7 @@ async def event_generator(
1397
1397
  )
1398
1398
 
1399
1399
  full_response = ""
1400
+ message_start = True
1400
1401
  async for item in llm_response:
1401
1402
  # Should not happen with async generator. Skip.
1402
1403
  if item is None or not isinstance(item, ResponseWithThought):
@@ -1410,10 +1411,11 @@ async def event_generator(
1410
1411
  async for result in send_event(ChatEvent.THOUGHT, item.thought):
1411
1412
  yield result
1412
1413
  continue
1413
-
1414
1414
  # Start sending response
1415
- async for result in send_event(ChatEvent.START_LLM_RESPONSE, ""):
1416
- yield result
1415
+ elif message_start:
1416
+ message_start = False
1417
+ async for result in send_event(ChatEvent.START_LLM_RESPONSE, ""):
1418
+ yield result
1417
1419
 
1418
1420
  try:
1419
1421
  async for result in send_event(ChatEvent.MESSAGE, message):
@@ -1423,6 +1425,13 @@ async def event_generator(
1423
1425
  logger.warning(f"Error during streaming. Stopping send: {e}")
1424
1426
  break
1425
1427
 
1428
+ # Check if the user has disconnected
1429
+ if cancellation_event.is_set():
1430
+ logger.debug(f"Stopping LLM response to user {user} on {common.client} client.")
1431
+ # Cancel the disconnect monitor task if it is still running
1432
+ await cancel_disconnect_monitor()
1433
+ return
1434
+
1426
1435
  # Save conversation once finish streaming
1427
1436
  asyncio.create_task(
1428
1437
  save_to_conversation_log(
@@ -1448,16 +1457,16 @@ async def event_generator(
1448
1457
  )
1449
1458
 
1450
1459
  # Signal end of LLM response after the loop finishes
1451
- if not cancellation_event.is_set():
1452
- async for result in send_event(ChatEvent.END_LLM_RESPONSE, ""):
1453
- yield result
1454
- # Send Usage Metadata once llm interactions are complete
1455
- if tracer.get("usage"):
1456
- async for event in send_event(ChatEvent.USAGE, tracer.get("usage")):
1457
- yield event
1458
- async for result in send_event(ChatEvent.END_RESPONSE, ""):
1459
- yield result
1460
- logger.debug("Finished streaming response")
1460
+ async for result in send_event(ChatEvent.END_LLM_RESPONSE, ""):
1461
+ yield result
1462
+
1463
+ # Send Usage Metadata once llm interactions are complete
1464
+ if tracer.get("usage"):
1465
+ async for event in send_event(ChatEvent.USAGE, tracer.get("usage")):
1466
+ yield event
1467
+ async for result in send_event(ChatEvent.END_RESPONSE, ""):
1468
+ yield result
1469
+ logger.debug("Finished streaming response")
1461
1470
 
1462
1471
  # Cancel the disconnect monitor task if it is still running
1463
1472
  await cancel_disconnect_monitor()
@@ -1509,8 +1518,7 @@ async def chat_ws(
1509
1518
  if data.get("type") == "interrupt":
1510
1519
  if current_task and not current_task.done():
1511
1520
  # Send interrupt signal to the ongoing task
1512
- abort_message = "␃🔚␗"
1513
- await interrupt_queue.put(data.get("query") or abort_message)
1521
+ await interrupt_queue.put(data.get("query") or ChatEvent.END_EVENT.value)
1514
1522
  logger.info(
1515
1523
  f"Interrupt signal sent to ongoing task for user {websocket.scope['user'].object.id} with query: {data.get('query')}"
1516
1524
  )
@@ -1533,8 +1541,8 @@ async def chat_ws(
1533
1541
 
1534
1542
  # Apply rate limiting manually
1535
1543
  try:
1536
- rate_limiter_per_minute.check_websocket(websocket)
1537
- rate_limiter_per_day.check_websocket(websocket)
1544
+ await rate_limiter_per_minute.check_websocket(websocket)
1545
+ await rate_limiter_per_day.check_websocket(websocket)
1538
1546
  image_rate_limiter.check_websocket(websocket, body)
1539
1547
  except HTTPException as e:
1540
1548
  await websocket.send_text(json.dumps({"error": e.detail}))
@@ -1572,6 +1580,37 @@ async def process_chat_request(
1572
1580
  interrupt_queue: asyncio.Queue,
1573
1581
  ):
1574
1582
  """Process a single chat request with interrupt support"""
1583
+
1584
+ # Server-side message buffering for better streaming performance
1585
+ @dataclass
1586
+ class MessageBuffer:
1587
+ """Buffer for managing streamed chat messages with timing control."""
1588
+
1589
+ content: str = ""
1590
+ timeout: Optional[asyncio.Task] = None
1591
+ last_flush: float = 0.0
1592
+
1593
+ def __post_init__(self):
1594
+ """Initialize last_flush with current time if not provided."""
1595
+ if self.last_flush == 0.0:
1596
+ self.last_flush = time.perf_counter()
1597
+
1598
+ message_buffer = MessageBuffer()
1599
+ BUFFER_FLUSH_INTERVAL = 0.1 # 100ms buffer interval
1600
+ BUFFER_MAX_SIZE = 512 # Flush if buffer reaches this size
1601
+
1602
+ async def flush_message_buffer():
1603
+ """Flush the accumulated message buffer to the client"""
1604
+ nonlocal message_buffer
1605
+ if message_buffer.content:
1606
+ buffered_content = message_buffer.content
1607
+ message_buffer.content = ""
1608
+ message_buffer.last_flush = time.perf_counter()
1609
+ if message_buffer.timeout:
1610
+ message_buffer.timeout.cancel()
1611
+ message_buffer.timeout = None
1612
+ yield buffered_content
1613
+
1575
1614
  try:
1576
1615
  # Since we are using websockets, we can ignore the stream parameter and always stream
1577
1616
  response_iterator = event_generator(
@@ -1583,7 +1622,43 @@ async def process_chat_request(
1583
1622
  interrupt_queue,
1584
1623
  )
1585
1624
  async for event in response_iterator:
1586
- await websocket.send_text(event)
1625
+ if event.startswith("{") and event.endswith("}"):
1626
+ evt_json = json.loads(event)
1627
+ if evt_json["type"] == ChatEvent.END_LLM_RESPONSE.value:
1628
+ # Flush remaining buffer content on end llm response event
1629
+ chunks = "".join([chunk async for chunk in flush_message_buffer()])
1630
+ await websocket.send_text(chunks)
1631
+ await websocket.send_text(ChatEvent.END_EVENT.value)
1632
+ await websocket.send_text(event)
1633
+ await websocket.send_text(ChatEvent.END_EVENT.value)
1634
+ elif event != ChatEvent.END_EVENT.value:
1635
+ # Buffer MESSAGE events for better streaming performance
1636
+ message_buffer.content += str(event)
1637
+
1638
+ # Flush if buffer is too large or enough time has passed
1639
+ current_time = time.perf_counter()
1640
+ should_flush_time = (current_time - message_buffer.last_flush) >= BUFFER_FLUSH_INTERVAL
1641
+ should_flush_size = len(message_buffer.content) >= BUFFER_MAX_SIZE
1642
+
1643
+ if should_flush_size or should_flush_time:
1644
+ chunks = "".join([chunk async for chunk in flush_message_buffer()])
1645
+ await websocket.send_text(chunks)
1646
+ await websocket.send_text(ChatEvent.END_EVENT.value)
1647
+ else:
1648
+ # Cancel any previous timeout tasks to reset the flush timer
1649
+ if message_buffer.timeout:
1650
+ message_buffer.timeout.cancel()
1651
+
1652
+ async def delayed_flush():
1653
+ """Flush message buffer if no new messages arrive within debounce interval."""
1654
+ await asyncio.sleep(BUFFER_FLUSH_INTERVAL)
1655
+ # Check if there's still content to flush
1656
+ chunks = "".join([chunk async for chunk in flush_message_buffer()])
1657
+ await websocket.send_text(chunks)
1658
+ await websocket.send_text(ChatEvent.END_EVENT.value)
1659
+
1660
+ # Flush buffer if no new messages arrive within debounce interval
1661
+ message_buffer.timeout = asyncio.create_task(delayed_flush())
1587
1662
  except asyncio.CancelledError:
1588
1663
  logger.debug(f"Chat request cancelled for user {websocket.scope['user'].object.id}")
1589
1664
  raise
khoj/routers/helpers.py CHANGED
@@ -1936,7 +1936,7 @@ class ApiUserRateLimiter:
1936
1936
  # Add the current request to the cache
1937
1937
  UserRequests.objects.create(user=user, slug=self.slug)
1938
1938
 
1939
- def check_websocket(self, websocket: WebSocket):
1939
+ async def check_websocket(self, websocket: WebSocket):
1940
1940
  """WebSocket-specific rate limiting method"""
1941
1941
  # Rate limiting disabled if billing is disabled
1942
1942
  if state.billing_enabled is False:
@@ -1954,7 +1954,7 @@ class ApiUserRateLimiter:
1954
1954
 
1955
1955
  # Remove requests outside of the time window
1956
1956
  cutoff = django_timezone.now() - timedelta(seconds=self.window)
1957
- count_requests = UserRequests.objects.filter(user=user, created_at__gte=cutoff, slug=self.slug).count()
1957
+ count_requests = await UserRequests.objects.filter(user=user, created_at__gte=cutoff, slug=self.slug).acount()
1958
1958
 
1959
1959
  # Check if the user has exceeded the rate limit
1960
1960
  if subscribed and count_requests >= self.subscribed_requests:
@@ -1984,7 +1984,7 @@ class ApiUserRateLimiter:
1984
1984
  )
1985
1985
 
1986
1986
  # Add the current request to the cache
1987
- UserRequests.objects.create(user=user, slug=self.slug)
1987
+ await UserRequests.objects.acreate(user=user, slug=self.slug)
1988
1988
 
1989
1989
 
1990
1990
  class ApiImageRateLimiter:
@@ -2099,7 +2099,8 @@ class WebSocketConnectionManager:
2099
2099
  user=user, slug__startswith=self.connection_slug_prefix
2100
2100
  ).acount()
2101
2101
 
2102
- return active_connections < max_connections
2102
+ # Restrict max active connections per user in production
2103
+ return active_connections < max_connections or state.anonymous_mode or in_debug_mode()
2103
2104
 
2104
2105
  async def register_connection(self, user: KhojUser, connection_id: str) -> None:
2105
2106
  """Register a new WebSocket connection."""
@@ -2616,7 +2617,6 @@ class MessageProcessor:
2616
2617
 
2617
2618
  async def read_chat_stream(response_iterator: AsyncGenerator[str, None]) -> Dict[str, Any]:
2618
2619
  processor = MessageProcessor()
2619
- event_delimiter = "␃🔚␗"
2620
2620
  buffer = ""
2621
2621
 
2622
2622
  async for chunk in response_iterator:
@@ -2624,9 +2624,9 @@ async def read_chat_stream(response_iterator: AsyncGenerator[str, None]) -> Dict
2624
2624
  buffer += chunk
2625
2625
 
2626
2626
  # Once the buffer contains a complete event
2627
- while event_delimiter in buffer:
2627
+ while ChatEvent.END_EVENT.value in buffer:
2628
2628
  # Extract the event from the buffer
2629
- event, buffer = buffer.split(event_delimiter, 1)
2629
+ event, buffer = buffer.split(ChatEvent.END_EVENT.value, 1)
2630
2630
  # Process the event
2631
2631
  if event:
2632
2632
  processor.process_message_chunk(event)
khoj/routers/research.py CHANGED
@@ -224,7 +224,7 @@ async def research(
224
224
  query_files: str = None,
225
225
  cancellation_event: Optional[asyncio.Event] = None,
226
226
  interrupt_queue: Optional[asyncio.Queue] = None,
227
- abort_message: str = "␃🔚␗",
227
+ abort_message: str = ChatEvent.END_EVENT.value,
228
228
  ):
229
229
  max_document_searches = 7
230
230
  max_online_searches = 3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: khoj
3
- Version: 2.0.0b9.dev11
3
+ Version: 2.0.0b11.dev9
4
4
  Summary: Your Second Brain
5
5
  Project-URL: Homepage, https://khoj.dev
6
6
  Project-URL: Documentation, https://docs.khoj.dev
@@ -131,17 +131,17 @@ khoj/interface/compiled/chat.svg,sha256=l2JoYRRgk201adTTdvJ-buKUrc0WGfsudix5xEvt
131
131
  khoj/interface/compiled/close.svg,sha256=hQ2iFLkNzHk0_iyTrSbwnWAeXYlgA-c2Eof2Iqh76n4,417
132
132
  khoj/interface/compiled/copy-button-success.svg,sha256=byqWAYD3Pn9IOXRjOKudJ-TJbP2UESbQGvtLWazNGjY,829
133
133
  khoj/interface/compiled/copy-button.svg,sha256=05bKM2eRxksfBlAPT7yMaoNJEk85bZCxQg67EVrPeHo,669
134
- khoj/interface/compiled/index.html,sha256=TGUTN_63D-X1aVP0VyCCsmDqS0YWpGXLu2G1okb_9Y8,53350
135
- khoj/interface/compiled/index.txt,sha256=HWJNJTHpKjYjv5JxmZ3U8UDX5vgBkzSgHl8smtVMgIk,7747
134
+ khoj/interface/compiled/index.html,sha256=2PgGpDUWrjEFT53ihFyfOtEDtAszPlumpPAeYgT194A,53350
135
+ khoj/interface/compiled/index.txt,sha256=dMtiguV4ec5Wx4wJwjTUmSSR_HvxcgjOgnpYELJMYxo,7747
136
136
  khoj/interface/compiled/khoj.webmanifest,sha256=9wOK2BMS6xH5NKd2eaUgTLg9WepIxB2K2U33KU89LD8,2543
137
137
  khoj/interface/compiled/logo.svg,sha256=_QCKVYM4WT2Qhcf7aVFImjq_s5CwjynGXYAOgI7yf8w,8059
138
138
  khoj/interface/compiled/send.svg,sha256=VdavOWkVddcwcGcld6pdfmwfz7S91M-9O28cfeiKJkM,635
139
139
  khoj/interface/compiled/share.svg,sha256=91lwo75PvMDrgocuZQab6EQ62CxRbubh9Bhw7CWMKbg,1221
140
140
  khoj/interface/compiled/thumbs-down.svg,sha256=JGNl-DwoRmH2XFMPWwFFklmoYtKxaQbkLE3nuYKe8ZY,1019
141
141
  khoj/interface/compiled/thumbs-up.svg,sha256=yS1wxTRtiztkN-6nZciLoYQUB_KTYNPV8xFRwH2TQFw,1036
142
- khoj/interface/compiled/404/index.html,sha256=Hl0LzE76huPyGjrt_ekFClWDCUTyAWoeOg5GHn701v4,17407
143
- khoj/interface/compiled/_next/static/M8PL43caF5dQgNQPB6Hd7/_buildManifest.js,sha256=f2_nYnw25hHWQJ-39Lf5OH1u6kgdbOInyfplqgjvAV4,224
144
- khoj/interface/compiled/_next/static/M8PL43caF5dQgNQPB6Hd7/_ssgManifest.js,sha256=Z49s4suAsf5y_GfnQSvm4qtq2ggxEbZPfEDTXjy6XgA,80
142
+ khoj/interface/compiled/404/index.html,sha256=r_d0AFatG83IhuLRhVaKMLnu4PwtW8oebi9aYIIxxN8,17407
143
+ khoj/interface/compiled/_next/static/JybcBQEMXcv7ZKN1xxi5F/_buildManifest.js,sha256=f2_nYnw25hHWQJ-39Lf5OH1u6kgdbOInyfplqgjvAV4,224
144
+ khoj/interface/compiled/_next/static/JybcBQEMXcv7ZKN1xxi5F/_ssgManifest.js,sha256=Z49s4suAsf5y_GfnQSvm4qtq2ggxEbZPfEDTXjy6XgA,80
145
145
  khoj/interface/compiled/_next/static/chunks/1191.b547ec13349b4aed.js,sha256=3qtdOft2SSaGT0qhyPunEraJEZUxIqDV4q3ULnFantg,10913
146
146
  khoj/interface/compiled/_next/static/chunks/1327-3b1a41af530fa8ee.js,sha256=7NmSOycXRGHpTN98sMAirnWN8ZUL971FsQpWmOs4Fxs,442974
147
147
  khoj/interface/compiled/_next/static/chunks/1588.f0558a0bdffc4761.js,sha256=ZSpLe7ui7FG7AvK00JHPg1YjYz8R9l1Obzu1mYHpzjo,89845
@@ -209,7 +209,7 @@ khoj/interface/compiled/_next/static/chunks/framework-8e0e0f4a6b83a956.js,sha256
209
209
  khoj/interface/compiled/_next/static/chunks/main-app-de1f09df97a3cfc7.js,sha256=bqnztujKItXfFBzQlaBmDZyfJpQt_M93CXOuchJfpD0,471
210
210
  khoj/interface/compiled/_next/static/chunks/main-fc8e0fefa2ef3d8c.js,sha256=t9FZIByh6V52m41LQ2yyAReF1CAuY7gLMBuWBeKCX2g,116793
211
211
  khoj/interface/compiled/_next/static/chunks/polyfills-42372ed130431b0a.js,sha256=CXPB1kyIrcjjyVBBDLWLKI9yEY1ZZbeASUON648vloM,112594
212
- khoj/interface/compiled/_next/static/chunks/webpack-4b00e5a0da4a9dae.js,sha256=1G9q97S90rcgHFal1FwdaGeIpYjsIyGZZibypp85R90,4951
212
+ khoj/interface/compiled/_next/static/chunks/webpack-92606a2523b656a3.js,sha256=xhMtbJm3MuU57r86XDuZDehXyBrHgydC7Kv5Y_SSpeI,4951
213
213
  khoj/interface/compiled/_next/static/chunks/app/layout-c2de87a25fededbb.js,sha256=jcU3C37p73V24B118uVRQffNaQES9jihsTGYF4fZ_8o,3949
214
214
  khoj/interface/compiled/_next/static/chunks/app/page-a19a597629e87fb8.js,sha256=lfXNkiSiwMKG1q3y0S3MUUsvQNznDHtfpwVKtx38gLk,29930
215
215
  khoj/interface/compiled/_next/static/chunks/app/_not-found/page-84f94d15b2da4eac.js,sha256=zElhiTkdu2JqrEvJ8Lrxh4HCyfLmPllBHHWOuDtrVlw,1755
@@ -229,10 +229,10 @@ khoj/interface/compiled/_next/static/chunks/pages/_app-3c9ca398d360b709.js,sha25
229
229
  khoj/interface/compiled/_next/static/chunks/pages/_error-cf5ca766ac8f493f.js,sha256=w_It3VzKT8O1M3CrJ_hZHsaU7M7dq3EAaVG8KvJ-fhU,253
230
230
  khoj/interface/compiled/_next/static/css/3090706713c12a32.css,sha256=lHBNcr2SPiAMdZQONh2MMlVM_huteuNSM9jCqGkS2d0,3075782
231
231
  khoj/interface/compiled/_next/static/css/37a73b87f02df402.css,sha256=hp0vlekKu0K2eITR5YIqFmLHQPqV3JETFnRd_-Uh0mk,165
232
- khoj/interface/compiled/_next/static/css/4398afc6d5a37666.css,sha256=L3JiJFYwMoIydyJcNoSLzGwlPxZ_ckAbyL6vnzWlPus,9736
233
232
  khoj/interface/compiled/_next/static/css/5b28ced915454767.css,sha256=Bk56AIRHovIWNUw8QWvMbXIxxPiyWEiObkMA7RwpMrs,4842
234
233
  khoj/interface/compiled/_next/static/css/76c658ee459140a9.css,sha256=7tI24VB66ZUsAPUxRdQhboopun0AXLUnF64uv9RkC08,1833
235
234
  khoj/interface/compiled/_next/static/css/7889a30fe9c83846.css,sha256=IUkZhkx4GpYOIhN-EJw9T1DqGMO3Wa3mNpUwaOBuZoY,7204
235
+ khoj/interface/compiled/_next/static/css/93eeacc43e261162.css,sha256=rbrg1ppryE0iLWmJexa3Qibtrb6gegftRjKIIMpnR2s,9736
236
236
  khoj/interface/compiled/_next/static/css/a0c2fd63bb396f04.css,sha256=8q0xBA3l7uP-YOqSnRnQEfPbGUgP9xRP0Q75UHSt6vc,34737
237
237
  khoj/interface/compiled/_next/static/css/db7d90554f3ab82b.css,sha256=A3ZAf0StEG3sr_LxAIizczSTYRe1NbtNUpfslvmkqgk,17713
238
238
  khoj/interface/compiled/_next/static/css/ea5485b3f3859a5a.css,sha256=tn6qi2xSLTWhtzDUE8UlC8iipH9QGV6A9oGj1ap-Sk4,1659
@@ -313,8 +313,8 @@ khoj/interface/compiled/_next/static/media/flags.3afdda2f.webp,sha256=M2AW_HLpBn
313
313
  khoj/interface/compiled/_next/static/media/flags@2x.5fbe9fc1.webp,sha256=BBeRPBZkxY3-aKkMnYv5TSkxmbeMbyUH4VRIPfrWg1E,137406
314
314
  khoj/interface/compiled/_next/static/media/globe.98e105ca.webp,sha256=g3ofb8-W9GM75zIhlvQhaS8I2py9TtrovOKR3_7Jf04,514
315
315
  khoj/interface/compiled/_next/static/media/globe@2x.974df6f8.webp,sha256=I_N7Yke3IOoS-0CC6XD8o0IUWG8PdPbrHmf6lpgWlZY,1380
316
- khoj/interface/compiled/agents/index.html,sha256=vI4EeZhoC4oio3D7uerkVQGJlUhL-tS7GElSDdshQ3s,16532
317
- khoj/interface/compiled/agents/index.txt,sha256=EewKHZDKIT3_cbS3GPRH4ETQ-Shnry-FSKYkSvoiPwU,7351
316
+ khoj/interface/compiled/agents/index.html,sha256=m52CXmiO-dxheGwkY4cXjWjj6EcnL5hN4cOJqfLTkns,16532
317
+ khoj/interface/compiled/agents/index.txt,sha256=074SUuOFvc2o7h1HntGg7hrb28iKhhkD5fCRo1bADHg,7351
318
318
  khoj/interface/compiled/assets/icons/khoj_lantern.ico,sha256=eggu-B_v3z1R53EjOFhIqqPnICBGdoaw1xnc0NrzHck,174144
319
319
  khoj/interface/compiled/assets/icons/khoj_lantern.svg,sha256=I_8XP5X84gEOoCRhCRKOQn_GKZrz3SUBXct7WxHvY7c,8767
320
320
  khoj/interface/compiled/assets/icons/khoj_lantern_1200x1200.png,sha256=xDx0bbD-WMflgg8zck9oPIIuTIvywtuED2k7CjSQS4w,66194
@@ -329,16 +329,16 @@ khoj/interface/compiled/assets/samples/desktop-remember-plan-sample.png,sha256=i
329
329
  khoj/interface/compiled/assets/samples/phone-browse-draw-sample.png,sha256=Dd4fPwtFl6BWqnHjeb1mCK_ND0hhHsWtx8sNE7EiMuE,406179
330
330
  khoj/interface/compiled/assets/samples/phone-plain-chat-sample.png,sha256=DEDaNRCkfEWUeh3kYZWIQDTVK1a6KKnYdwj5ZWisN_Q,82985
331
331
  khoj/interface/compiled/assets/samples/phone-remember-plan-sample.png,sha256=Ma3blirRmq3X4oYSsDbbT7MDn29rymDrjwmUfA9BMuM,236285
332
- khoj/interface/compiled/automations/index.html,sha256=73wL38RaqpifrofDevHJGseHYx8cyQw56zeOsbJ-3bw,54402
333
- khoj/interface/compiled/automations/index.txt,sha256=fqhXqUS9FLY63eaqZ1Wbh5bm1gX1uqQlzzrXIM-oX1M,7580
334
- khoj/interface/compiled/chat/index.html,sha256=PKvZRcMNp2xmBywIDkxTX5GJ1QF-o4H62X0A1xJumm8,53532
335
- khoj/interface/compiled/chat/index.txt,sha256=eEA4bLEv-jZlOvW9cJw6quVJwwLS5hE6m0MkurHnoek,7991
336
- khoj/interface/compiled/search/index.html,sha256=kuwOkluK8aMmOOAMMEL4pyjoiLAipxZAJqlpmuM37tU,55611
337
- khoj/interface/compiled/search/index.txt,sha256=Z-U60golNM0trlcjvU_85_O-cZACvPbRXRSdw4qbFAU,6698
338
- khoj/interface/compiled/settings/index.html,sha256=DMkwSD0ZSHJeyGIG8S034yDwGS1-NjJPNmMpkYF4Cgg,53050
339
- khoj/interface/compiled/settings/index.txt,sha256=2M4acAWXTTN-Hw4O3_mR6GYzvNw_FH499lkXTl1yvDk,7834
340
- khoj/interface/compiled/share/chat/index.html,sha256=hM9DNt0M9gF_lIRkVaRvGfYAArPa3Y4H73Fn44-ZvkA,54112
341
- khoj/interface/compiled/share/chat/index.txt,sha256=PLRGbktsBKe2vb8ronCrRwoR_uRp3QTllBInpyHksGY,8453
332
+ khoj/interface/compiled/automations/index.html,sha256=CieQ74X2PteimNQlVc9MEF3tJSNY5hVXFnn0z-sWWCQ,54402
333
+ khoj/interface/compiled/automations/index.txt,sha256=oaQxYO0fwDKuaKAG5ov-j_uFGKpzNmLRjB1WWw773gM,7580
334
+ khoj/interface/compiled/chat/index.html,sha256=It1p_bYIyeiTadQvLKsuuSTa22iVuiUepJEuRrCrc_o,53532
335
+ khoj/interface/compiled/chat/index.txt,sha256=4HlMUr-pCeM4Jd2Rjbf_6YQShvdeszZgpyGVHibeSdg,7991
336
+ khoj/interface/compiled/search/index.html,sha256=ulqmGh3-KngA330baVspMO277rNuOy50oiBmTMk0Rws,55611
337
+ khoj/interface/compiled/search/index.txt,sha256=YzhCVVuAguja1qCIQFtxW4cZiiHbnZ915aB_EqtukHA,6698
338
+ khoj/interface/compiled/settings/index.html,sha256=462F5RXQacN00vkXgylbeeOkD-VIwEusYAKr6D2A-AE,53050
339
+ khoj/interface/compiled/settings/index.txt,sha256=qSNa_TRpiiPsfptoT_59zO6r3tB_EStYCSAIboyQzBI,7834
340
+ khoj/interface/compiled/share/chat/index.html,sha256=UijXuZSBLgDFKkht1ak_KR-EDHndWw4hyPScpX0_Bpo,54112
341
+ khoj/interface/compiled/share/chat/index.txt,sha256=OHEVOu2vc0FmB2UlZNwVmEaSH9zXW0mL7yiLxcbbJgU,8453
342
342
  khoj/interface/email/feedback.html,sha256=xksuPFamx4hGWyTTxZKRgX_eiYQQEuv-eK9Xmkt-nwU,1216
343
343
  khoj/interface/email/magic_link.html,sha256=372ESbTPKM9acekuZcOIKOw6kBl-KikFg_L9MOHqJkg,2094
344
344
  khoj/interface/email/task.html,sha256=tY7a0gzVeQ2lSQNu7WyXR_s7VYeWTrxWEj1iHVuoVE4,2813
@@ -391,7 +391,7 @@ khoj/processor/content/plaintext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk
391
391
  khoj/processor/content/plaintext/plaintext_to_entries.py,sha256=wFZwK_zIc7gWbRtO9sOHo9KvfhGAzL9psX_nKWYFduo,4975
392
392
  khoj/processor/conversation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
393
393
  khoj/processor/conversation/prompts.py,sha256=F0MVg81Tr7L4W7ubx_UJ-D4PqgGCElTg8KLpQjdPuIk,54207
394
- khoj/processor/conversation/utils.py,sha256=bpl6y5CWqVShE8fBbpZSl9-aOTGNiBjwXXAORy5ebck,48589
394
+ khoj/processor/conversation/utils.py,sha256=ts7tMK3H4IrShop7hBNDyO1ZCXLrCIFgmPKsR5QjN-s,48618
395
395
  khoj/processor/conversation/anthropic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
396
396
  khoj/processor/conversation/anthropic/anthropic_chat.py,sha256=6IG-YlpFx86EgW3PdGuv4xGMRzvHx4xVUcQMqkKn4vs,5358
397
397
  khoj/processor/conversation/anthropic/utils.py,sha256=Z7mz-LnunLHubZvdzNEAozlJxukl2eNoLvYzeYzsglc,16568
@@ -404,11 +404,11 @@ khoj/processor/conversation/offline/utils.py,sha256=51McImxl6u1qgRYvMt7uzsgLGSLq
404
404
  khoj/processor/conversation/offline/whisper.py,sha256=DJI-8y8DULO2cQ49m2VOvRyIZ2TxBypc15gM8O3HuMI,470
405
405
  khoj/processor/conversation/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
406
406
  khoj/processor/conversation/openai/gpt.py,sha256=w-VeVoI8xTyS1n36y0sbI2TPP6v-LFriFx9xyfgnt7g,6096
407
- khoj/processor/conversation/openai/utils.py,sha256=0P-vjY4ip4T3ZZg-VI0y8WgOzppr7m0WI2035vsWU9w,36624
407
+ khoj/processor/conversation/openai/utils.py,sha256=G9MAfVJ0iKw8u8KMDXpfsuMarjhAKyGqPCqwSEwrMFw,37778
408
408
  khoj/processor/conversation/openai/whisper.py,sha256=zoEeK1LNCg_tzP4xzYi5vRPzNPGuDGzpkrkG7d1LUn4,447
409
409
  khoj/processor/image/generate.py,sha256=bF80fjsHKkU2f2ADiXJei8-ViqcT0EHaM0wH78KPUC8,12199
410
410
  khoj/processor/operator/README.md,sha256=QaV00W1IB7i8ZrvhNkpjmFMVDtORFt-OASieRQGE_UE,2308
411
- khoj/processor/operator/__init__.py,sha256=NXvGaW3wvWH1WpYq7uABPThXgkabLlp3ijnFPf5QRn8,11182
411
+ khoj/processor/operator/__init__.py,sha256=xMth9GHyBGFM1mMYDUdaMhA7sxzVAsEcSor4PFMuXCA,11195
412
412
  khoj/processor/operator/grounding_agent.py,sha256=eyWCaIHg12Ak2SbCl7aiiFSoDZ88-AlrqQElRDdDXDE,18917
413
413
  khoj/processor/operator/grounding_agent_uitars.py,sha256=Ujdug_Z2_r1tZmy5kBtHbZcqOp0jSH-7ZnYo1fVdcDQ,42261
414
414
  khoj/processor/operator/operator_actions.py,sha256=eJHxs6idstIbGzzRPHsveuJxl5jH9dHvBhOxuAqjg7M,4268
@@ -428,16 +428,16 @@ khoj/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
428
428
  khoj/routers/api.py,sha256=BFiKwdYjkR-4aHBumM7Hu4XdN2RvQ0Z9V4_2Wd8aPiM,8633
429
429
  khoj/routers/api_agents.py,sha256=QcognyY9FwClgOZw21BF9K7IX16i2070kRoM7c_bKn8,17264
430
430
  khoj/routers/api_automation.py,sha256=ux990dRLbcFadV01T-1McPwvFeR0KLyrWAVpCJ3YLvk,9399
431
- khoj/routers/api_chat.py,sha256=_kerg-eHFmBUW9f_kd3XHZzE0nzWm2RPOljSpgh73nc,63331
431
+ khoj/routers/api_chat.py,sha256=u351tDt2iKOS8VVL0fCRUseQOLRsGcmSwuEvEIUCk8g,66993
432
432
  khoj/routers/api_content.py,sha256=GFChoWm4nYdilhzB1ElbJjaJJRfLn8XtkKmLnZOUHrU,24580
433
433
  khoj/routers/api_model.py,sha256=hjIgOQqva4YVv1osQK8p-317_oSKsv1mHbAYFQICxnM,5273
434
434
  khoj/routers/api_phone.py,sha256=p9yfc4WeMHDC0hg3aQk60a2VBy8rZPdEnz9wdJ7DzkU,2208
435
435
  khoj/routers/api_subscription.py,sha256=_Z3gwW5348qrF7sF9rqwkeG291KX5olr9Fd_-ri9faE,6480
436
436
  khoj/routers/auth.py,sha256=jk2lqAS_650lQsoaOFTlZd9W_LL8HbN5zhHTZza_lqs,11258
437
437
  khoj/routers/email.py,sha256=wvr6_fpk0RuKcTPC6suI8JDZPLYzJ9hAhz_G41yZytc,3923
438
- khoj/routers/helpers.py,sha256=-S8MQ5ZOKIjq6u6vhwFffR0fyw4XxQyi85xy2Ov3FOE,123430
438
+ khoj/routers/helpers.py,sha256=6WNn-uQLgB1ZNRWCVBgw_Bk24988ZCzCW6IrqL_e_N0,123543
439
439
  khoj/routers/notion.py,sha256=g53xyYFmjr2JnuIrTW2vytbfkiK_UkoRTxqnnLSmD5o,2802
440
- khoj/routers/research.py,sha256=XO8oO9okfMMWFC4JpJ-lR7vDpf6_-HTjGJcNAUd2HC8,26380
440
+ khoj/routers/research.py,sha256=UyMOzLglNT26CFZ2w11_DVycP3fnpEYICewOo9L9p4U,26393
441
441
  khoj/routers/storage.py,sha256=lao0DvsF49QleZvOdjKM98RU2cGfCJDBb7WeoI7Rr3I,2172
442
442
  khoj/routers/twilio.py,sha256=MLsuCm4--ETvr3sLxbF0CL_ehlg_l2rKBSLR2Qh2Xls,1081
443
443
  khoj/routers/web_client.py,sha256=_vyfDaHZZjNoI2LwGNQFRiFmGLkNcgYJe7dOr3mrxH8,4386
@@ -460,8 +460,8 @@ khoj/utils/models.py,sha256=Q5tcC9-z25sCiub048fLnvZ6_IIO1bcPNxt5payekk0,2009
460
460
  khoj/utils/rawconfig.py,sha256=lgq0FfJOkdALLkoISjmBSEnzuaTPShsTuFUbXlf6brk,5406
461
461
  khoj/utils/state.py,sha256=s_GFWOqRzpEDx0eCPStuzBTK2VEw-qgRpH0aiEdGnDo,1791
462
462
  khoj/utils/yaml.py,sha256=qy1Tkc61rDMesBw_Cyx2vOR6H-Hngcsm5kYfjwQBwkE,1543
463
- khoj-2.0.0b9.dev11.dist-info/METADATA,sha256=DfpPt9JqpU2JuFLmT4F617NvO4vyPopESyThkn6vKNo,8974
464
- khoj-2.0.0b9.dev11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
465
- khoj-2.0.0b9.dev11.dist-info/entry_points.txt,sha256=KBIcez5N_jCgq_ER4Uxf-e1lxTBMTE_BBjMwwfeZyAg,39
466
- khoj-2.0.0b9.dev11.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
467
- khoj-2.0.0b9.dev11.dist-info/RECORD,,
463
+ khoj-2.0.0b11.dev9.dist-info/METADATA,sha256=PXpFXUG03naxZXz9VGn-2T495Zzy1Kzy5M1CVeC77G4,8974
464
+ khoj-2.0.0b11.dev9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
465
+ khoj-2.0.0b11.dev9.dist-info/entry_points.txt,sha256=KBIcez5N_jCgq_ER4Uxf-e1lxTBMTE_BBjMwwfeZyAg,39
466
+ khoj-2.0.0b11.dev9.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
467
+ khoj-2.0.0b11.dev9.dist-info/RECORD,,