khoj 1.16.1.dev25__py3-none-any.whl → 1.17.1.dev216__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- khoj/configure.py +6 -6
- khoj/database/adapters/__init__.py +55 -26
- khoj/database/migrations/0053_agent_style_color_agent_style_icon.py +61 -0
- khoj/database/models/__init__.py +35 -0
- khoj/interface/web/assets/icons/favicon-128x128.png +0 -0
- khoj/interface/web/assets/icons/favicon-256x256.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways-200.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways-500.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways.svg +31 -5384
- khoj/interface/web/assets/icons/khoj.svg +26 -0
- khoj/interface/web/chat.html +191 -301
- khoj/interface/web/content_source_computer_input.html +3 -3
- khoj/interface/web/content_source_github_input.html +1 -1
- khoj/interface/web/content_source_notion_input.html +1 -1
- khoj/interface/web/public_conversation.html +1 -1
- khoj/interface/web/search.html +2 -2
- khoj/interface/web/{config.html → settings.html} +30 -30
- khoj/interface/web/utils.html +1 -1
- khoj/processor/content/docx/docx_to_entries.py +4 -9
- khoj/processor/content/github/github_to_entries.py +1 -3
- khoj/processor/content/images/image_to_entries.py +4 -9
- khoj/processor/content/markdown/markdown_to_entries.py +4 -9
- khoj/processor/content/notion/notion_to_entries.py +1 -3
- khoj/processor/content/org_mode/org_to_entries.py +4 -9
- khoj/processor/content/pdf/pdf_to_entries.py +4 -9
- khoj/processor/content/plaintext/plaintext_to_entries.py +4 -9
- khoj/processor/content/text_to_entries.py +1 -3
- khoj/processor/conversation/utils.py +0 -4
- khoj/processor/tools/online_search.py +13 -7
- khoj/routers/api.py +58 -9
- khoj/routers/api_agents.py +3 -1
- khoj/routers/api_chat.py +335 -562
- khoj/routers/api_content.py +538 -0
- khoj/routers/api_model.py +156 -0
- khoj/routers/helpers.py +338 -23
- khoj/routers/notion.py +2 -8
- khoj/routers/web_client.py +43 -256
- khoj/search_type/text_search.py +5 -4
- khoj/utils/fs_syncer.py +4 -2
- khoj/utils/rawconfig.py +6 -1
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/METADATA +2 -2
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/RECORD +45 -43
- khoj/routers/api_config.py +0 -434
- khoj/routers/indexer.py +0 -349
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/WHEEL +0 -0
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/entry_points.txt +0 -0
- {khoj-1.16.1.dev25.dist-info → khoj-1.17.1.dev216.dist-info}/licenses/LICENSE +0 -0
khoj/routers/api.py
CHANGED
|
@@ -6,7 +6,6 @@ import os
|
|
|
6
6
|
import threading
|
|
7
7
|
import time
|
|
8
8
|
import uuid
|
|
9
|
-
from random import random
|
|
10
9
|
from typing import Any, Callable, List, Optional, Union
|
|
11
10
|
|
|
12
11
|
import cron_descriptor
|
|
@@ -20,6 +19,7 @@ from fastapi.responses import Response
|
|
|
20
19
|
from starlette.authentication import has_required_scope, requires
|
|
21
20
|
|
|
22
21
|
from khoj.configure import initialize_content
|
|
22
|
+
from khoj.database import adapters
|
|
23
23
|
from khoj.database.adapters import (
|
|
24
24
|
AutomationAdapters,
|
|
25
25
|
ConversationAdapters,
|
|
@@ -37,9 +37,11 @@ from khoj.processor.conversation.openai.gpt import extract_questions
|
|
|
37
37
|
from khoj.processor.conversation.openai.whisper import transcribe_audio
|
|
38
38
|
from khoj.routers.helpers import (
|
|
39
39
|
ApiUserRateLimiter,
|
|
40
|
+
ChatEvent,
|
|
40
41
|
CommonQueryParams,
|
|
41
42
|
ConversationCommandRateLimiter,
|
|
42
43
|
acreate_title_from_query,
|
|
44
|
+
get_user_config,
|
|
43
45
|
schedule_automation,
|
|
44
46
|
update_telemetry_state,
|
|
45
47
|
)
|
|
@@ -190,7 +192,7 @@ def update(
|
|
|
190
192
|
):
|
|
191
193
|
user = request.user.object
|
|
192
194
|
if not state.config:
|
|
193
|
-
error_msg = f"🚨 Khoj is not configured.\nConfigure it via http://localhost:42110/
|
|
195
|
+
error_msg = f"🚨 Khoj is not configured.\nConfigure it via http://localhost:42110/settings, plugins or by editing {state.config_file}."
|
|
194
196
|
logger.warning(error_msg)
|
|
195
197
|
raise HTTPException(status_code=500, detail=error_msg)
|
|
196
198
|
try:
|
|
@@ -223,10 +225,10 @@ async def transcribe(
|
|
|
223
225
|
common: CommonQueryParams,
|
|
224
226
|
file: UploadFile = File(...),
|
|
225
227
|
rate_limiter_per_minute=Depends(
|
|
226
|
-
ApiUserRateLimiter(requests=
|
|
228
|
+
ApiUserRateLimiter(requests=20, subscribed_requests=20, window=60, slug="transcribe_minute")
|
|
227
229
|
),
|
|
228
230
|
rate_limiter_per_day=Depends(
|
|
229
|
-
ApiUserRateLimiter(requests=
|
|
231
|
+
ApiUserRateLimiter(requests=60, subscribed_requests=600, window=60 * 60 * 24, slug="transcribe_day")
|
|
230
232
|
),
|
|
231
233
|
):
|
|
232
234
|
user: KhojUser = request.user.object
|
|
@@ -277,6 +279,49 @@ async def transcribe(
|
|
|
277
279
|
return Response(content=content, media_type="application/json", status_code=200)
|
|
278
280
|
|
|
279
281
|
|
|
282
|
+
@api.get("/settings", response_class=Response)
|
|
283
|
+
@requires(["authenticated"])
|
|
284
|
+
def get_settings(request: Request, detailed: Optional[bool] = False) -> Response:
|
|
285
|
+
user = request.user.object
|
|
286
|
+
user_config = get_user_config(user, request, is_detailed=detailed)
|
|
287
|
+
del user_config["request"]
|
|
288
|
+
|
|
289
|
+
# Return config data as a JSON response
|
|
290
|
+
return Response(content=json.dumps(user_config), media_type="application/json", status_code=200)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
@api.patch("/user/name", status_code=200)
|
|
294
|
+
@requires(["authenticated"])
|
|
295
|
+
def set_user_name(
|
|
296
|
+
request: Request,
|
|
297
|
+
name: str,
|
|
298
|
+
client: Optional[str] = None,
|
|
299
|
+
):
|
|
300
|
+
user = request.user.object
|
|
301
|
+
|
|
302
|
+
split_name = name.split(" ")
|
|
303
|
+
|
|
304
|
+
if len(split_name) > 2:
|
|
305
|
+
raise HTTPException(status_code=400, detail="Name must be in the format: Firstname Lastname")
|
|
306
|
+
|
|
307
|
+
if len(split_name) == 1:
|
|
308
|
+
first_name = split_name[0]
|
|
309
|
+
last_name = ""
|
|
310
|
+
else:
|
|
311
|
+
first_name, last_name = split_name[0], split_name[-1]
|
|
312
|
+
|
|
313
|
+
adapters.set_user_name(user, first_name, last_name)
|
|
314
|
+
|
|
315
|
+
update_telemetry_state(
|
|
316
|
+
request=request,
|
|
317
|
+
telemetry_type="api",
|
|
318
|
+
api="set_user_name",
|
|
319
|
+
client=client,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
return {"status": "ok"}
|
|
323
|
+
|
|
324
|
+
|
|
280
325
|
async def extract_references_and_questions(
|
|
281
326
|
request: Request,
|
|
282
327
|
meta_log: dict,
|
|
@@ -298,11 +343,13 @@ async def extract_references_and_questions(
|
|
|
298
343
|
not ConversationCommand.Notes in conversation_commands
|
|
299
344
|
and not ConversationCommand.Default in conversation_commands
|
|
300
345
|
):
|
|
301
|
-
|
|
346
|
+
yield compiled_references, inferred_queries, q
|
|
347
|
+
return
|
|
302
348
|
|
|
303
349
|
if not await sync_to_async(EntryAdapters.user_has_entries)(user=user):
|
|
304
350
|
logger.debug("No documents in knowledge base. Use a Khoj client to sync and chat with your docs.")
|
|
305
|
-
|
|
351
|
+
yield compiled_references, inferred_queries, q
|
|
352
|
+
return
|
|
306
353
|
|
|
307
354
|
# Extract filter terms from user message
|
|
308
355
|
defiltered_query = q
|
|
@@ -313,7 +360,8 @@ async def extract_references_and_questions(
|
|
|
313
360
|
|
|
314
361
|
if not conversation:
|
|
315
362
|
logger.error(f"Conversation with id {conversation_id} not found.")
|
|
316
|
-
|
|
363
|
+
yield compiled_references, inferred_queries, defiltered_query
|
|
364
|
+
return
|
|
317
365
|
|
|
318
366
|
filters_in_query += " ".join([f'file:"{filter}"' for filter in conversation.file_filters])
|
|
319
367
|
using_offline_chat = False
|
|
@@ -373,7 +421,8 @@ async def extract_references_and_questions(
|
|
|
373
421
|
logger.info(f"🔍 Searching knowledge base with queries: {inferred_queries}")
|
|
374
422
|
if send_status_func:
|
|
375
423
|
inferred_queries_str = "\n- " + "\n- ".join(inferred_queries)
|
|
376
|
-
|
|
424
|
+
async for event in send_status_func(f"**Searching Documents for:** {inferred_queries_str}"):
|
|
425
|
+
yield {ChatEvent.STATUS: event}
|
|
377
426
|
for query in inferred_queries:
|
|
378
427
|
n_items = min(n, 3) if using_offline_chat else n
|
|
379
428
|
search_results.extend(
|
|
@@ -392,7 +441,7 @@ async def extract_references_and_questions(
|
|
|
392
441
|
{"compiled": item.additional["compiled"], "file": item.additional["file"]} for item in search_results
|
|
393
442
|
]
|
|
394
443
|
|
|
395
|
-
|
|
444
|
+
yield compiled_references, inferred_queries, defiltered_query
|
|
396
445
|
|
|
397
446
|
|
|
398
447
|
@api.get("/health", response_class=Response)
|
khoj/routers/api_agents.py
CHANGED
|
@@ -30,10 +30,12 @@ async def all_agents(
|
|
|
30
30
|
"slug": agent.slug,
|
|
31
31
|
"avatar": agent.avatar,
|
|
32
32
|
"name": agent.name,
|
|
33
|
-
"
|
|
33
|
+
"persona": agent.personality,
|
|
34
34
|
"public": agent.public,
|
|
35
35
|
"creator": agent.creator.username if agent.creator else None,
|
|
36
36
|
"managed_by_admin": agent.managed_by_admin,
|
|
37
|
+
"color": agent.style_color,
|
|
38
|
+
"icon": agent.style_icon,
|
|
37
39
|
}
|
|
38
40
|
)
|
|
39
41
|
|