khoj 2.0.0b13.dev5__py3-none-any.whl → 2.0.0b13.dev19__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/app/README.md +1 -1
- khoj/app/urls.py +1 -0
- khoj/database/adapters/__init__.py +4 -4
- khoj/database/management/commands/delete_orphaned_fileobjects.py +0 -1
- khoj/database/migrations/0064_remove_conversation_temp_id_alter_conversation_id.py +1 -1
- khoj/database/migrations/0075_migrate_generated_assets_and_validate.py +1 -1
- khoj/database/models/__init__.py +6 -6
- khoj/database/tests.py +0 -2
- khoj/interface/compiled/404/index.html +2 -2
- khoj/interface/compiled/_next/static/chunks/{9245.a04e92d034540234.js → 1225.ecac11e7421504c4.js} +3 -3
- khoj/interface/compiled/_next/static/chunks/1320.ae930ad00affe685.js +5 -0
- khoj/interface/compiled/_next/static/chunks/{1327-3b1a41af530fa8ee.js → 1327-511bb0a862efce80.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/1626.15a8acc0d6639ec6.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{3489.c523fe96a2eee74f.js → 1940.d082758bd04e08ae.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/{2327-ea623ca2d22f78e9.js → 2327-fe87dd989d71d0eb.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/2475.57a0d0fd93d07af0.js +93 -0
- khoj/interface/compiled/_next/static/chunks/2481.5ce6524ba0a73f90.js +55 -0
- khoj/interface/compiled/_next/static/chunks/297.4c4c823ff6e3255b.js +174 -0
- khoj/interface/compiled/_next/static/chunks/{5639-09e2009a2adedf8b.js → 3260-43d3019b92c315bb.js} +68 -23
- khoj/interface/compiled/_next/static/chunks/3353.1c6d553216a1acae.js +1 -0
- khoj/interface/compiled/_next/static/chunks/3855.f7b8131f78af046e.js +1 -0
- khoj/interface/compiled/_next/static/chunks/3973.dc54a39586ab48be.js +1 -0
- khoj/interface/compiled/_next/static/chunks/4241.c1cd170f7f37ac59.js +24 -0
- khoj/interface/compiled/_next/static/chunks/{4327.8d2a1b8f1ea78208.js → 4327.f3704dc398c67113.js} +19 -19
- khoj/interface/compiled/_next/static/chunks/4505.f09454a346269c3f.js +117 -0
- khoj/interface/compiled/_next/static/chunks/4801.96a152d49742b644.js +1 -0
- khoj/interface/compiled/_next/static/chunks/5427-a95ec748e52abb75.js +1 -0
- khoj/interface/compiled/_next/static/chunks/549.2bd27f59a91a9668.js +148 -0
- khoj/interface/compiled/_next/static/chunks/5765.71b1e1207b76b03f.js +1 -0
- khoj/interface/compiled/_next/static/chunks/584.d7ce3505f169b706.js +1 -0
- khoj/interface/compiled/_next/static/chunks/6240.34f7c1fa692edd61.js +24 -0
- khoj/interface/compiled/_next/static/chunks/6d3fe5a5-f9f3c16e0bc0cdf9.js +10 -0
- khoj/interface/compiled/_next/static/chunks/{7127-0f4a2a77d97fb5fa.js → 7127-97b83757db125ba6.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/7200-93ab0072359b8028.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{2612.bcf5a623b3da209e.js → 7553.f5ad54b1f6e92c49.js} +2 -2
- khoj/interface/compiled/_next/static/chunks/7626-1b630f1654172341.js +1 -0
- khoj/interface/compiled/_next/static/chunks/764.dadd316e8e16d191.js +63 -0
- khoj/interface/compiled/_next/static/chunks/78.08169ab541abab4f.js +43 -0
- khoj/interface/compiled/_next/static/chunks/784.e03acf460df213d1.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{9537-d9ab442ce15d1e20.js → 8072-e1440cb482a0940e.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/{3265.924139c4146ee344.js → 8086.8d39887215807fcd.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/8168.f074ab8c7c16d82d.js +59 -0
- khoj/interface/compiled/_next/static/chunks/{8694.2bd9c2f65d8c5847.js → 8223.1705878fa7a09292.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/8483.94f6c9e2bee86f50.js +215 -0
- khoj/interface/compiled/_next/static/chunks/{8888.ebe0e552b59e7fed.js → 8810.fc0e479de78c7c61.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/8828.bc74dc4ce94e78f6.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{7303.d0612f812a967a08.js → 8909.14ac3f43d0070cf1.js} +5 -5
- khoj/interface/compiled/_next/static/chunks/90542734.b1a1629065ba199b.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9167.098534184f03fe92.js +56 -0
- khoj/interface/compiled/_next/static/chunks/{4980.63500d68b3bb1222.js → 9537.e934ce37bf314509.js} +5 -5
- khoj/interface/compiled/_next/static/chunks/9574.3fe8e26e95bf1c34.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9599.ec50b5296c27dae9.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9643.b34248df52ffc77c.js +262 -0
- khoj/interface/compiled/_next/static/chunks/9747.2fd9065b1435abb1.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9922.98f2b2a9959b4ebe.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/agents/page-e291b49977f43880.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/automations/page-198b26df6e09bbb0.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/chat/{page-8e1c4f2af3c9429e.js → page-9a75d7369f2a7cd2.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/{page-2b3056cba8aa96ce.js → page-1567cac7b79a7c59.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/settings/{page-8be3b35178abf2ec.js → page-6081362437c82470.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/share/chat/{page-4a4b0c0f4749c2b2.js → page-e0dcb1762f8c8f88.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/webpack-d60b0c57a6c38d0f.js +1 -0
- khoj/interface/compiled/agents/index.html +2 -2
- khoj/interface/compiled/agents/index.txt +3 -3
- khoj/interface/compiled/automations/index.html +2 -2
- khoj/interface/compiled/automations/index.txt +3 -3
- khoj/interface/compiled/chat/index.html +2 -2
- khoj/interface/compiled/chat/index.txt +3 -3
- khoj/interface/compiled/index.html +2 -2
- khoj/interface/compiled/index.txt +3 -3
- khoj/interface/compiled/search/index.html +2 -2
- khoj/interface/compiled/search/index.txt +3 -3
- khoj/interface/compiled/settings/index.html +2 -2
- khoj/interface/compiled/settings/index.txt +3 -3
- khoj/interface/compiled/share/chat/index.html +2 -2
- khoj/interface/compiled/share/chat/index.txt +3 -3
- khoj/main.py +3 -3
- khoj/manage.py +1 -0
- khoj/processor/content/github/github_to_entries.py +6 -6
- khoj/processor/content/images/image_to_entries.py +0 -1
- khoj/processor/content/markdown/markdown_to_entries.py +2 -3
- khoj/processor/content/notion/notion_to_entries.py +5 -5
- khoj/processor/content/org_mode/org_to_entries.py +4 -5
- khoj/processor/content/org_mode/orgnode.py +4 -4
- khoj/processor/content/plaintext/plaintext_to_entries.py +1 -2
- khoj/processor/content/text_to_entries.py +1 -2
- khoj/processor/conversation/google/utils.py +3 -3
- khoj/processor/conversation/openai/utils.py +3 -4
- khoj/processor/conversation/utils.py +17 -11
- khoj/processor/embeddings.py +0 -2
- khoj/processor/image/generate.py +3 -3
- khoj/processor/operator/__init__.py +2 -2
- khoj/processor/operator/grounding_agent.py +15 -2
- khoj/processor/operator/grounding_agent_uitars.py +34 -23
- khoj/processor/operator/operator_agent_anthropic.py +29 -4
- khoj/processor/operator/operator_agent_base.py +1 -1
- khoj/processor/operator/operator_agent_binary.py +4 -4
- khoj/processor/operator/operator_agent_openai.py +21 -6
- khoj/processor/operator/operator_environment_browser.py +1 -1
- khoj/processor/operator/operator_environment_computer.py +1 -1
- khoj/processor/speech/text_to_speech.py +0 -1
- khoj/processor/tools/online_search.py +1 -1
- khoj/processor/tools/run_code.py +1 -1
- khoj/routers/api.py +1 -2
- khoj/routers/api_agents.py +1 -2
- khoj/routers/api_automation.py +1 -1
- khoj/routers/api_chat.py +10 -16
- khoj/routers/api_model.py +0 -1
- khoj/routers/api_subscription.py +1 -1
- khoj/routers/email.py +4 -4
- khoj/routers/helpers.py +17 -20
- khoj/routers/research.py +2 -4
- khoj/search_filter/base_filter.py +2 -4
- khoj/search_type/text_search.py +1 -2
- khoj/utils/helpers.py +4 -4
- khoj/utils/initialization.py +1 -3
- khoj/utils/models.py +2 -4
- khoj/utils/rawconfig.py +1 -2
- khoj/utils/state.py +1 -1
- {khoj-2.0.0b13.dev5.dist-info → khoj-2.0.0b13.dev19.dist-info}/METADATA +3 -2
- {khoj-2.0.0b13.dev5.dist-info → khoj-2.0.0b13.dev19.dist-info}/RECORD +127 -125
- khoj/interface/compiled/_next/static/chunks/1191.b547ec13349b4aed.js +0 -1
- khoj/interface/compiled/_next/static/chunks/1588.f0558a0bdffc4761.js +0 -117
- khoj/interface/compiled/_next/static/chunks/1918.925cb4a35518d258.js +0 -43
- khoj/interface/compiled/_next/static/chunks/2849.dc00ae5ba7219cfc.js +0 -1
- khoj/interface/compiled/_next/static/chunks/303.fe76de943e930fbd.js +0 -1
- khoj/interface/compiled/_next/static/chunks/4533.586e74b45a2bde25.js +0 -55
- khoj/interface/compiled/_next/static/chunks/4551.82ce1476b5516bc2.js +0 -5
- khoj/interface/compiled/_next/static/chunks/4748.0edd37cba3ea2809.js +0 -59
- khoj/interface/compiled/_next/static/chunks/5210.cd35a1c1ec594a20.js +0 -93
- khoj/interface/compiled/_next/static/chunks/5329.f8b3c5b3d16159cd.js +0 -1
- khoj/interface/compiled/_next/static/chunks/5427-13d6ffd380fdfab7.js +0 -1
- khoj/interface/compiled/_next/static/chunks/558-c14e76cff03f6a60.js +0 -1
- khoj/interface/compiled/_next/static/chunks/5830.8876eccb82da9b7d.js +0 -262
- khoj/interface/compiled/_next/static/chunks/6230.88a71d8145347b3f.js +0 -1
- khoj/interface/compiled/_next/static/chunks/7161.77e0530a40ad5ca8.js +0 -1
- khoj/interface/compiled/_next/static/chunks/7200-ac3b2e37ff30e126.js +0 -1
- khoj/interface/compiled/_next/static/chunks/7505.c31027a3695bdebb.js +0 -148
- khoj/interface/compiled/_next/static/chunks/7760.35649cc21d9585bd.js +0 -56
- khoj/interface/compiled/_next/static/chunks/83.48e2db193a940052.js +0 -1
- khoj/interface/compiled/_next/static/chunks/8427.844694e06133fb51.js +0 -1
- khoj/interface/compiled/_next/static/chunks/8665.4db7e6b2e8933497.js +0 -174
- khoj/interface/compiled/_next/static/chunks/872.caf84cc1a39ae59f.js +0 -1
- khoj/interface/compiled/_next/static/chunks/8890.6e8a59e4de6978bc.js +0 -215
- khoj/interface/compiled/_next/static/chunks/8950.5f2272e0ac923f9e.js +0 -1
- khoj/interface/compiled/_next/static/chunks/90542734.2c21f16f18b22411.js +0 -1
- khoj/interface/compiled/_next/static/chunks/9202.c703864fcedc8d1f.js +0 -63
- khoj/interface/compiled/_next/static/chunks/9320.6aca4885d541aa44.js +0 -24
- khoj/interface/compiled/_next/static/chunks/9535.f78cd92d03331e55.js +0 -1
- khoj/interface/compiled/_next/static/chunks/9968.b111fc002796da81.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/agents/page-9a4610474cd59a71.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/automations/page-f7bb9d777b7745d4.js +0 -1
- khoj/interface/compiled/_next/static/chunks/f3e3247b-1758d4651e4457c2.js +0 -10
- khoj/interface/compiled/_next/static/chunks/webpack-ee14d29b64c5ab47.js +0 -1
- /khoj/interface/compiled/_next/static/{XfWrWDAk5VXeZ88OdP652 → N-GdBSXoYe-DuObnbXVRO}/_buildManifest.js +0 -0
- /khoj/interface/compiled/_next/static/{XfWrWDAk5VXeZ88OdP652 → N-GdBSXoYe-DuObnbXVRO}/_ssgManifest.js +0 -0
- /khoj/interface/compiled/_next/static/chunks/app/search/{page-4885df3cd175c957.js → page-3639e50ec3e9acfd.js} +0 -0
- {khoj-2.0.0b13.dev5.dist-info → khoj-2.0.0b13.dev19.dist-info}/WHEEL +0 -0
- {khoj-2.0.0b13.dev5.dist-info → khoj-2.0.0b13.dev19.dist-info}/entry_points.txt +0 -0
- {khoj-2.0.0b13.dev5.dist-info → khoj-2.0.0b13.dev19.dist-info}/licenses/LICENSE +0 -0
khoj/routers/api_automation.py
CHANGED
@@ -109,7 +109,7 @@ def post_automation(
|
|
109
109
|
except Exception as e:
|
110
110
|
logger.error(f"Error creating automation {q} for {user.email}: {e}", exc_info=True)
|
111
111
|
return Response(
|
112
|
-
content=
|
112
|
+
content="Unable to create automation. Ensure the automation doesn't already exist.",
|
113
113
|
media_type="text/plain",
|
114
114
|
status_code=500,
|
115
115
|
)
|
khoj/routers/api_chat.py
CHANGED
@@ -10,7 +10,6 @@ from functools import partial
|
|
10
10
|
from typing import Any, Dict, List, Optional
|
11
11
|
from urllib.parse import unquote
|
12
12
|
|
13
|
-
from asgiref.sync import sync_to_async
|
14
13
|
from fastapi import (
|
15
14
|
APIRouter,
|
16
15
|
Depends,
|
@@ -32,10 +31,10 @@ from khoj.database.adapters import (
|
|
32
31
|
PublicConversationAdapters,
|
33
32
|
aget_user_name,
|
34
33
|
)
|
35
|
-
from khoj.database.models import Agent,
|
34
|
+
from khoj.database.models import Agent, KhojUser
|
36
35
|
from khoj.processor.conversation import prompts
|
37
36
|
from khoj.processor.conversation.openai.utils import is_local_api
|
38
|
-
from khoj.processor.conversation.prompts import
|
37
|
+
from khoj.processor.conversation.prompts import no_entries_found
|
39
38
|
from khoj.processor.conversation.utils import (
|
40
39
|
OperatorRun,
|
41
40
|
ResponseWithThought,
|
@@ -65,11 +64,8 @@ from khoj.routers.helpers import (
|
|
65
64
|
acreate_title_from_history,
|
66
65
|
agenerate_chat_response,
|
67
66
|
aget_data_sources_and_output_format,
|
68
|
-
construct_automation_created_message,
|
69
|
-
create_automation,
|
70
67
|
gather_raw_query_files,
|
71
68
|
generate_mermaidjs_diagram,
|
72
|
-
generate_summary_from_files,
|
73
69
|
get_conversation_command,
|
74
70
|
get_message_from_queue,
|
75
71
|
is_query_empty,
|
@@ -89,13 +85,11 @@ from khoj.utils.helpers import (
|
|
89
85
|
convert_image_to_webp,
|
90
86
|
get_country_code_from_timezone,
|
91
87
|
get_country_name_from_timezone,
|
92
|
-
get_device,
|
93
88
|
is_env_var_true,
|
94
89
|
is_none_or_empty,
|
95
90
|
is_operator_enabled,
|
96
91
|
)
|
97
92
|
from khoj.utils.rawconfig import (
|
98
|
-
ChatRequestBody,
|
99
93
|
FileAttachment,
|
100
94
|
FileFilterRequest,
|
101
95
|
FilesFilterRequest,
|
@@ -689,7 +683,6 @@ async def event_generator(
|
|
689
683
|
region = body.region
|
690
684
|
country = body.country or get_country_name_from_timezone(body.timezone)
|
691
685
|
country_code = body.country_code or get_country_code_from_timezone(body.timezone)
|
692
|
-
timezone = body.timezone
|
693
686
|
raw_images = body.images
|
694
687
|
raw_query_files = body.files
|
695
688
|
|
@@ -853,7 +846,8 @@ async def event_generator(
|
|
853
846
|
if (
|
854
847
|
len(train_of_thought) > 0
|
855
848
|
and train_of_thought[-1]["type"] == ChatEvent.THOUGHT.value
|
856
|
-
and
|
849
|
+
and isinstance(train_of_thought[-1]["data"], str)
|
850
|
+
and isinstance(data, str)
|
857
851
|
):
|
858
852
|
train_of_thought[-1]["data"] += data
|
859
853
|
else:
|
@@ -1075,11 +1069,11 @@ async def event_generator(
|
|
1075
1069
|
|
1076
1070
|
# researched_results = await extract_relevant_info(q, researched_results, agent)
|
1077
1071
|
if state.verbose > 1:
|
1078
|
-
logger.debug(f
|
1072
|
+
logger.debug(f"Researched Results: {''.join(r.summarizedResult or '' for r in research_results)}")
|
1079
1073
|
|
1080
1074
|
# Gather Context
|
1081
1075
|
## Extract Document References
|
1082
|
-
if
|
1076
|
+
if ConversationCommand.Research not in conversation_commands:
|
1083
1077
|
try:
|
1084
1078
|
async for result in search_documents(
|
1085
1079
|
q,
|
@@ -1218,7 +1212,7 @@ async def event_generator(
|
|
1218
1212
|
else:
|
1219
1213
|
code_results = result
|
1220
1214
|
except ValueError as e:
|
1221
|
-
program_execution_context.append(
|
1215
|
+
program_execution_context.append("Failed to run code")
|
1222
1216
|
logger.warning(
|
1223
1217
|
f"Failed to use code tool: {e}. Attempting to respond without code results",
|
1224
1218
|
exc_info=True,
|
@@ -1297,7 +1291,7 @@ async def event_generator(
|
|
1297
1291
|
inferred_queries.append(improved_image_prompt)
|
1298
1292
|
if generated_image is None or status_code != 200:
|
1299
1293
|
program_execution_context.append(f"Failed to generate image with {improved_image_prompt}")
|
1300
|
-
async for result in send_event(ChatEvent.STATUS,
|
1294
|
+
async for result in send_event(ChatEvent.STATUS, "Failed to generate image"):
|
1301
1295
|
yield result
|
1302
1296
|
else:
|
1303
1297
|
generated_images.append(generated_image)
|
@@ -1315,7 +1309,7 @@ async def event_generator(
|
|
1315
1309
|
yield result
|
1316
1310
|
|
1317
1311
|
if ConversationCommand.Diagram in conversation_commands:
|
1318
|
-
async for result in send_event(ChatEvent.STATUS,
|
1312
|
+
async for result in send_event(ChatEvent.STATUS, "Creating diagram"):
|
1319
1313
|
yield result
|
1320
1314
|
|
1321
1315
|
inferred_queries = []
|
@@ -1372,7 +1366,7 @@ async def event_generator(
|
|
1372
1366
|
return
|
1373
1367
|
|
1374
1368
|
## Generate Text Output
|
1375
|
-
async for result in send_event(ChatEvent.STATUS,
|
1369
|
+
async for result in send_event(ChatEvent.STATUS, "**Generating a well-informed response**"):
|
1376
1370
|
yield result
|
1377
1371
|
|
1378
1372
|
llm_response, chat_metadata = await agenerate_chat_response(
|
khoj/routers/api_model.py
CHANGED
khoj/routers/api_subscription.py
CHANGED
@@ -117,7 +117,7 @@ async def subscribe(request: Request):
|
|
117
117
|
)
|
118
118
|
logger.log(logging.INFO, f"🥳 New User Created: {user.user.uuid}")
|
119
119
|
|
120
|
-
logger.info(f
|
120
|
+
logger.info(f"Stripe subscription {event['type']} for {customer_email}")
|
121
121
|
return {"success": success}
|
122
122
|
|
123
123
|
|
khoj/routers/email.py
CHANGED
@@ -44,7 +44,7 @@ async def send_magic_link_email(email, unique_id, host):
|
|
44
44
|
{
|
45
45
|
"sender": os.environ.get("RESEND_EMAIL", "noreply@khoj.dev"),
|
46
46
|
"to": email,
|
47
|
-
"subject":
|
47
|
+
"subject": "Your login code to Khoj",
|
48
48
|
"html": html_content,
|
49
49
|
}
|
50
50
|
)
|
@@ -98,11 +98,11 @@ async def send_query_feedback(uquery, kquery, sentiment, user_email):
|
|
98
98
|
user_email=user_email if not is_none_or_empty(user_email) else "N/A",
|
99
99
|
)
|
100
100
|
# send feedback to fixed account
|
101
|
-
|
101
|
+
resend.Emails.send(
|
102
102
|
{
|
103
103
|
"sender": os.environ.get("RESEND_EMAIL", "noreply@khoj.dev"),
|
104
104
|
"to": "team@khoj.dev",
|
105
|
-
"subject":
|
105
|
+
"subject": "User Feedback",
|
106
106
|
"html": html_content,
|
107
107
|
}
|
108
108
|
)
|
@@ -127,7 +127,7 @@ def send_task_email(name, email, query, result, subject, is_image=False):
|
|
127
127
|
|
128
128
|
r = resend.Emails.send(
|
129
129
|
{
|
130
|
-
"sender": f
|
130
|
+
"sender": f"Khoj <{os.environ.get('RESEND_EMAIL', 'khoj@khoj.dev')}>",
|
131
131
|
"to": email,
|
132
132
|
"subject": f"✨ {subject}",
|
133
133
|
"html": html_content,
|
khoj/routers/helpers.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import asyncio
|
2
2
|
import base64
|
3
|
-
import concurrent.futures
|
4
3
|
import fnmatch
|
5
4
|
import hashlib
|
6
5
|
import json
|
@@ -47,14 +46,12 @@ from khoj.database.adapters import (
|
|
47
46
|
EntryAdapters,
|
48
47
|
FileObjectAdapters,
|
49
48
|
aget_user_by_email,
|
50
|
-
ais_user_subscribed,
|
51
49
|
create_khoj_token,
|
52
50
|
get_default_search_model,
|
53
51
|
get_khoj_tokens,
|
54
52
|
get_user_name,
|
55
53
|
get_user_notion_config,
|
56
54
|
get_user_subscription_state,
|
57
|
-
is_user_subscribed,
|
58
55
|
run_with_process_lock,
|
59
56
|
)
|
60
57
|
from khoj.database.models import (
|
@@ -160,7 +157,7 @@ def validate_chat_model(user: KhojUser):
|
|
160
157
|
|
161
158
|
async def is_ready_to_chat(user: KhojUser):
|
162
159
|
user_chat_model = await ConversationAdapters.aget_user_chat_model(user)
|
163
|
-
if user_chat_model
|
160
|
+
if user_chat_model is None:
|
164
161
|
user_chat_model = await ConversationAdapters.aget_default_chat_model(user)
|
165
162
|
|
166
163
|
if (
|
@@ -581,7 +578,7 @@ async def generate_online_subqueries(
|
|
581
578
|
)
|
582
579
|
return {q}
|
583
580
|
return response
|
584
|
-
except Exception
|
581
|
+
except Exception:
|
585
582
|
logger.error(f"Invalid response for constructing online subqueries: {response}. Returning original query: {q}")
|
586
583
|
return {q}
|
587
584
|
|
@@ -1172,8 +1169,8 @@ async def search_documents(
|
|
1172
1169
|
agent_has_entries = await sync_to_async(EntryAdapters.agent_has_entries)(agent=agent)
|
1173
1170
|
|
1174
1171
|
if (
|
1175
|
-
|
1176
|
-
and
|
1172
|
+
ConversationCommand.Notes not in conversation_commands
|
1173
|
+
and ConversationCommand.Default not in conversation_commands
|
1177
1174
|
and not agent_has_entries
|
1178
1175
|
):
|
1179
1176
|
yield compiled_references, inferred_queries, q
|
@@ -1325,8 +1322,8 @@ async def extract_questions(
|
|
1325
1322
|
logger.error(f"Invalid response for constructing subqueries: {response}")
|
1326
1323
|
return [query]
|
1327
1324
|
return queries
|
1328
|
-
except:
|
1329
|
-
logger.warning(
|
1325
|
+
except Exception:
|
1326
|
+
logger.warning("LLM returned invalid JSON. Falling back to using user message as search query.")
|
1330
1327
|
return [query]
|
1331
1328
|
|
1332
1329
|
|
@@ -1351,7 +1348,7 @@ async def execute_search(
|
|
1351
1348
|
return results
|
1352
1349
|
|
1353
1350
|
if q is None or q == "":
|
1354
|
-
logger.warning(
|
1351
|
+
logger.warning("No query param (q) passed in API call to initiate search")
|
1355
1352
|
return results
|
1356
1353
|
|
1357
1354
|
# initialize variables
|
@@ -1364,7 +1361,7 @@ async def execute_search(
|
|
1364
1361
|
if user:
|
1365
1362
|
query_cache_key = f"{user_query}-{n}-{t}-{r}-{max_distance}-{dedupe}"
|
1366
1363
|
if query_cache_key in state.query_cache[user.uuid]:
|
1367
|
-
logger.debug(
|
1364
|
+
logger.debug("Return response from query cache")
|
1368
1365
|
return state.query_cache[user.uuid][query_cache_key]
|
1369
1366
|
|
1370
1367
|
# Encode query with filter terms removed
|
@@ -1875,8 +1872,8 @@ class ApiUserRateLimiter:
|
|
1875
1872
|
|
1876
1873
|
user: KhojUser = websocket.scope["user"].object
|
1877
1874
|
subscribed = has_required_scope(websocket, ["premium"])
|
1878
|
-
current_window = "today" if self.window == 60 * 60 * 24 else
|
1879
|
-
next_window = "tomorrow" if self.window == 60 * 60 * 24 else
|
1875
|
+
current_window = "today" if self.window == 60 * 60 * 24 else "now"
|
1876
|
+
next_window = "tomorrow" if self.window == 60 * 60 * 24 else "in a bit"
|
1880
1877
|
common_message_prefix = f"I'm glad you're enjoying interacting with me! You've unfortunately exceeded your usage limit for {current_window}."
|
1881
1878
|
|
1882
1879
|
# Remove requests outside of the time window
|
@@ -2219,7 +2216,7 @@ def should_notify(original_query: str, executed_query: str, ai_response: str, us
|
|
2219
2216
|
should_notify_result = response["decision"] == "Yes"
|
2220
2217
|
reason = response.get("reason", "unknown")
|
2221
2218
|
logger.info(
|
2222
|
-
f
|
2219
|
+
f"Decided to {'not ' if not should_notify_result else ''}notify user of automation response because of reason: {reason}."
|
2223
2220
|
)
|
2224
2221
|
return should_notify_result
|
2225
2222
|
except Exception as e:
|
@@ -2313,7 +2310,7 @@ def scheduled_chat(
|
|
2313
2310
|
response_map = raw_response.json()
|
2314
2311
|
ai_response = response_map.get("response") or response_map.get("image")
|
2315
2312
|
is_image = False
|
2316
|
-
if
|
2313
|
+
if isinstance(ai_response, dict):
|
2317
2314
|
is_image = ai_response.get("image") is not None
|
2318
2315
|
else:
|
2319
2316
|
ai_response = raw_response.text
|
@@ -2460,12 +2457,12 @@ async def aschedule_automation(
|
|
2460
2457
|
|
2461
2458
|
def construct_automation_created_message(automation: Job, crontime: str, query_to_run: str, subject: str):
|
2462
2459
|
# Display next run time in user timezone instead of UTC
|
2463
|
-
schedule = f
|
2460
|
+
schedule = f"{cron_descriptor.get_description(crontime)} {automation.next_run_time.strftime('%Z')}"
|
2464
2461
|
next_run_time = automation.next_run_time.strftime("%Y-%m-%d %I:%M %p %Z")
|
2465
2462
|
# Remove /automated_task prefix from inferred_query
|
2466
2463
|
unprefixed_query_to_run = re.sub(r"^\/automated_task\s*", "", query_to_run)
|
2467
2464
|
# Create the automation response
|
2468
|
-
automation_icon_url =
|
2465
|
+
automation_icon_url = "/static/assets/icons/automation.svg"
|
2469
2466
|
return f"""
|
2470
2467
|
###  Created Automation
|
2471
2468
|
- Subject: **{subject}**
|
@@ -2713,13 +2710,13 @@ def configure_content(
|
|
2713
2710
|
t: Optional[state.SearchType] = state.SearchType.All,
|
2714
2711
|
) -> bool:
|
2715
2712
|
success = True
|
2716
|
-
if t
|
2713
|
+
if t is None:
|
2717
2714
|
t = state.SearchType.All
|
2718
2715
|
|
2719
2716
|
if t is not None and t in [type.value for type in state.SearchType]:
|
2720
2717
|
t = state.SearchType(t)
|
2721
2718
|
|
2722
|
-
if t is not None and
|
2719
|
+
if t is not None and t.value not in [type.value for type in state.SearchType]:
|
2723
2720
|
logger.warning(f"🚨 Invalid search type: {t}")
|
2724
2721
|
return False
|
2725
2722
|
|
@@ -2988,7 +2985,7 @@ async def grep_files(
|
|
2988
2985
|
query += f" {' and '.join(context_info)}"
|
2989
2986
|
if line_count > max_results:
|
2990
2987
|
if lines_before or lines_after:
|
2991
|
-
query +=
|
2988
|
+
query += " for"
|
2992
2989
|
query += f" first {max_results} results"
|
2993
2990
|
return query
|
2994
2991
|
|
khoj/routers/research.py
CHANGED
@@ -15,7 +15,6 @@ from khoj.processor.conversation.utils import (
|
|
15
15
|
ResearchIteration,
|
16
16
|
ToolCall,
|
17
17
|
construct_iteration_history,
|
18
|
-
construct_structured_message,
|
19
18
|
construct_tool_chat_history,
|
20
19
|
load_complex_json,
|
21
20
|
)
|
@@ -24,7 +23,6 @@ from khoj.processor.tools.online_search import read_webpages_content, search_onl
|
|
24
23
|
from khoj.processor.tools.run_code import run_code
|
25
24
|
from khoj.routers.helpers import (
|
26
25
|
ChatEvent,
|
27
|
-
generate_summary_from_files,
|
28
26
|
get_message_from_queue,
|
29
27
|
grep_files,
|
30
28
|
list_files,
|
@@ -184,7 +182,7 @@ async def apick_next_tool(
|
|
184
182
|
# TODO: Handle multiple tool calls.
|
185
183
|
response_text = response.text
|
186
184
|
parsed_response = [ToolCall(**item) for item in load_complex_json(response_text)][0]
|
187
|
-
except Exception
|
185
|
+
except Exception:
|
188
186
|
# Otherwise assume the model has decided to end the research run and respond to the user.
|
189
187
|
parsed_response = ToolCall(name=ConversationCommand.Text, args={"response": response_text}, id=None)
|
190
188
|
|
@@ -199,7 +197,7 @@ async def apick_next_tool(
|
|
199
197
|
if i.warning is None and isinstance(i.query, ToolCall)
|
200
198
|
}
|
201
199
|
if (parsed_response.name, dict_to_tuple(parsed_response.args)) in previous_tool_query_combinations:
|
202
|
-
warning =
|
200
|
+
warning = "Repeated tool, query combination detected. Skipping iteration. Try something different."
|
203
201
|
# Only send client status updates if we'll execute this iteration and model has thoughts to share.
|
204
202
|
elif send_status_func and not is_none_or_empty(response.thought):
|
205
203
|
async for event in send_status_func(response.thought):
|
@@ -4,12 +4,10 @@ from typing import List
|
|
4
4
|
|
5
5
|
class BaseFilter(ABC):
|
6
6
|
@abstractmethod
|
7
|
-
def get_filter_terms(self, query: str) -> List[str]:
|
8
|
-
...
|
7
|
+
def get_filter_terms(self, query: str) -> List[str]: ...
|
9
8
|
|
10
9
|
def can_filter(self, raw_query: str) -> bool:
|
11
10
|
return len(self.get_filter_terms(raw_query)) > 0
|
12
11
|
|
13
12
|
@abstractmethod
|
14
|
-
def defilter(self, query: str) -> str:
|
15
|
-
...
|
13
|
+
def defilter(self, query: str) -> str: ...
|
khoj/search_type/text_search.py
CHANGED
@@ -9,9 +9,8 @@ from asgiref.sync import sync_to_async
|
|
9
9
|
from sentence_transformers import util
|
10
10
|
|
11
11
|
from khoj.database.adapters import EntryAdapters, get_default_search_model
|
12
|
-
from khoj.database.models import Agent
|
12
|
+
from khoj.database.models import Agent, KhojUser
|
13
13
|
from khoj.database.models import Entry as DbEntry
|
14
|
-
from khoj.database.models import KhojUser
|
15
14
|
from khoj.processor.content.text_to_entries import TextToEntries
|
16
15
|
from khoj.utils import state
|
17
16
|
from khoj.utils.helpers import get_absolute_path, timer
|
khoj/utils/helpers.py
CHANGED
@@ -77,7 +77,7 @@ class AsyncIteratorWrapper:
|
|
77
77
|
|
78
78
|
|
79
79
|
def is_none_or_empty(item):
|
80
|
-
return item
|
80
|
+
return item is None or (hasattr(item, "__iter__") and len(item) == 0) or item == ""
|
81
81
|
|
82
82
|
|
83
83
|
def to_snake_case_from_dash(item: str):
|
@@ -97,7 +97,7 @@ def get_from_dict(dictionary, *args):
|
|
97
97
|
Returns: dictionary[args[0]][args[1]]... or None if any keys missing"""
|
98
98
|
current = dictionary
|
99
99
|
for arg in args:
|
100
|
-
if not hasattr(current, "__iter__") or not
|
100
|
+
if not hasattr(current, "__iter__") or arg not in current:
|
101
101
|
return None
|
102
102
|
current = current[arg]
|
103
103
|
return current
|
@@ -751,7 +751,7 @@ def is_valid_url(url: str) -> bool:
|
|
751
751
|
try:
|
752
752
|
result = urlparse(url.strip())
|
753
753
|
return all([result.scheme, result.netloc])
|
754
|
-
except:
|
754
|
+
except Exception:
|
755
755
|
return False
|
756
756
|
|
757
757
|
|
@@ -759,7 +759,7 @@ def is_internet_connected():
|
|
759
759
|
try:
|
760
760
|
response = requests.head("https://www.google.com")
|
761
761
|
return response.status_code == 200
|
762
|
-
except:
|
762
|
+
except Exception:
|
763
763
|
return False
|
764
764
|
|
765
765
|
|
khoj/utils/initialization.py
CHANGED
@@ -60,9 +60,7 @@ def initialization(interactive: bool = True):
|
|
60
60
|
]
|
61
61
|
default_chat_models = known_available_models + other_available_models
|
62
62
|
except Exception as e:
|
63
|
-
logger.warning(
|
64
|
-
f"⚠️ Failed to fetch {provider} chat models. Fallback to default models. Error: {str(e)}"
|
65
|
-
)
|
63
|
+
logger.warning(f"⚠️ Failed to fetch {provider} chat models. Fallback to default models. Error: {str(e)}")
|
66
64
|
|
67
65
|
# Set up OpenAI's online chat models
|
68
66
|
openai_configured, openai_provider = _setup_chat_model_provider(
|
khoj/utils/models.py
CHANGED
@@ -8,12 +8,10 @@ from tqdm import trange
|
|
8
8
|
|
9
9
|
class BaseEncoder(ABC):
|
10
10
|
@abstractmethod
|
11
|
-
def __init__(self, model_name: str, device: torch.device = None, **kwargs):
|
12
|
-
...
|
11
|
+
def __init__(self, model_name: str, device: torch.device = None, **kwargs): ...
|
13
12
|
|
14
13
|
@abstractmethod
|
15
|
-
def encode(self, entries: List[str], device: torch.device = None, **kwargs) -> torch.Tensor:
|
16
|
-
...
|
14
|
+
def encode(self, entries: List[str], device: torch.device = None, **kwargs) -> torch.Tensor: ...
|
17
15
|
|
18
16
|
|
19
17
|
class OpenAI(BaseEncoder):
|
khoj/utils/rawconfig.py
CHANGED
khoj/utils/state.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: khoj
|
3
|
-
Version: 2.0.0b13.
|
3
|
+
Version: 2.0.0b13.dev19
|
4
4
|
Summary: Your Second Brain
|
5
5
|
Project-URL: Homepage, https://khoj.dev
|
6
6
|
Project-URL: Documentation, https://docs.khoj.dev
|
@@ -27,6 +27,7 @@ Requires-Dist: anyio~=4.8.0
|
|
27
27
|
Requires-Dist: apscheduler~=3.10.0
|
28
28
|
Requires-Dist: authlib==1.2.1
|
29
29
|
Requires-Dist: beautifulsoup4~=4.12.3
|
30
|
+
Requires-Dist: click<8.2.2
|
30
31
|
Requires-Dist: cron-descriptor==1.4.3
|
31
32
|
Requires-Dist: dateparser>=1.1.1
|
32
33
|
Requires-Dist: defusedxml==0.7.1
|
@@ -78,7 +79,6 @@ Requires-Dist: tzdata==2023.3
|
|
78
79
|
Requires-Dist: uvicorn==0.30.6
|
79
80
|
Requires-Dist: websockets==13.0
|
80
81
|
Provides-Extra: dev
|
81
|
-
Requires-Dist: black>=23.1.0; extra == 'dev'
|
82
82
|
Requires-Dist: boto3>=1.34.57; extra == 'dev'
|
83
83
|
Requires-Dist: datasets; extra == 'dev'
|
84
84
|
Requires-Dist: factory-boy>=3.2.1; extra == 'dev'
|
@@ -93,6 +93,7 @@ Requires-Dist: pytest-asyncio==0.21.1; extra == 'dev'
|
|
93
93
|
Requires-Dist: pytest-django==4.5.2; extra == 'dev'
|
94
94
|
Requires-Dist: pytest-xdist[psutil]; extra == 'dev'
|
95
95
|
Requires-Dist: pytest>=7.1.2; extra == 'dev'
|
96
|
+
Requires-Dist: ruff>=0.12.0; extra == 'dev'
|
96
97
|
Requires-Dist: stripe==7.3.0; extra == 'dev'
|
97
98
|
Requires-Dist: twilio==8.11; extra == 'dev'
|
98
99
|
Provides-Extra: local
|