khoj 1.16.1.dev15__py3-none-any.whl → 1.16.1.dev47__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/database/adapters/__init__.py +9 -10
- khoj/interface/web/chat.html +186 -296
- khoj/processor/conversation/anthropic/anthropic_chat.py +10 -4
- khoj/processor/conversation/offline/chat_model.py +19 -7
- khoj/processor/conversation/offline/utils.py +2 -0
- khoj/processor/conversation/openai/gpt.py +9 -3
- khoj/processor/conversation/prompts.py +56 -25
- khoj/processor/conversation/utils.py +5 -6
- khoj/processor/tools/online_search.py +13 -7
- khoj/routers/api.py +12 -7
- khoj/routers/api_chat.py +264 -483
- khoj/routers/helpers.py +33 -21
- khoj/routers/indexer.py +1 -1
- khoj/utils/fs_syncer.py +1 -1
- {khoj-1.16.1.dev15.dist-info → khoj-1.16.1.dev47.dist-info}/METADATA +2 -2
- {khoj-1.16.1.dev15.dist-info → khoj-1.16.1.dev47.dist-info}/RECORD +19 -19
- {khoj-1.16.1.dev15.dist-info → khoj-1.16.1.dev47.dist-info}/WHEEL +0 -0
- {khoj-1.16.1.dev15.dist-info → khoj-1.16.1.dev47.dist-info}/entry_points.txt +0 -0
- {khoj-1.16.1.dev15.dist-info → khoj-1.16.1.dev47.dist-info}/licenses/LICENSE +0 -0
khoj/routers/helpers.py
CHANGED
|
@@ -8,6 +8,7 @@ import math
|
|
|
8
8
|
import re
|
|
9
9
|
from concurrent.futures import ThreadPoolExecutor
|
|
10
10
|
from datetime import datetime, timedelta, timezone
|
|
11
|
+
from enum import Enum
|
|
11
12
|
from functools import partial
|
|
12
13
|
from random import random
|
|
13
14
|
from typing import (
|
|
@@ -307,6 +308,7 @@ async def aget_relevant_output_modes(query: str, conversation_history: dict, is_
|
|
|
307
308
|
# Check whether the tool exists as a valid ConversationCommand
|
|
308
309
|
return ConversationCommand(response)
|
|
309
310
|
|
|
311
|
+
logger.error(f"Invalid output mode selected: {response}. Defaulting to text.")
|
|
310
312
|
return ConversationCommand.Text
|
|
311
313
|
except Exception:
|
|
312
314
|
logger.error(f"Invalid response for determining relevant mode: {response}")
|
|
@@ -519,9 +521,6 @@ async def send_message_to_model_wrapper(
|
|
|
519
521
|
chat_model_option or await ConversationAdapters.aget_default_conversation_config()
|
|
520
522
|
)
|
|
521
523
|
|
|
522
|
-
if conversation_config is None:
|
|
523
|
-
raise HTTPException(status_code=500, detail="Contact the server administrator to set a default chat model.")
|
|
524
|
-
|
|
525
524
|
chat_model = conversation_config.chat_model
|
|
526
525
|
max_tokens = conversation_config.max_prompt_size
|
|
527
526
|
tokenizer = conversation_config.tokenizer
|
|
@@ -755,7 +754,7 @@ async def text_to_image(
|
|
|
755
754
|
references: List[Dict[str, Any]],
|
|
756
755
|
online_results: Dict[str, Any],
|
|
757
756
|
send_status_func: Optional[Callable] = None,
|
|
758
|
-
)
|
|
757
|
+
):
|
|
759
758
|
status_code = 200
|
|
760
759
|
image = None
|
|
761
760
|
response = None
|
|
@@ -767,7 +766,8 @@ async def text_to_image(
|
|
|
767
766
|
# If the user has not configured a text to image model, return an unsupported on server error
|
|
768
767
|
status_code = 501
|
|
769
768
|
message = "Failed to generate image. Setup image generation on the server."
|
|
770
|
-
|
|
769
|
+
yield image_url or image, status_code, message, intent_type.value
|
|
770
|
+
return
|
|
771
771
|
|
|
772
772
|
text2image_model = text_to_image_config.model_name
|
|
773
773
|
chat_history = ""
|
|
@@ -779,20 +779,21 @@ async def text_to_image(
|
|
|
779
779
|
chat_history += f"Q: Prompt: {chat['intent']['query']}\n"
|
|
780
780
|
chat_history += f"A: Improved Prompt: {chat['intent']['inferred-queries'][0]}\n"
|
|
781
781
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
782
|
+
if send_status_func:
|
|
783
|
+
async for event in send_status_func("**✍🏽 Enhancing the Painting Prompt**"):
|
|
784
|
+
yield {ChatEvent.STATUS: event}
|
|
785
|
+
improved_image_prompt = await generate_better_image_prompt(
|
|
786
|
+
message,
|
|
787
|
+
chat_history,
|
|
788
|
+
location_data=location_data,
|
|
789
|
+
note_references=references,
|
|
790
|
+
online_results=online_results,
|
|
791
|
+
model_type=text_to_image_config.model_type,
|
|
792
|
+
)
|
|
793
793
|
|
|
794
794
|
if send_status_func:
|
|
795
|
-
|
|
795
|
+
async for event in send_status_func(f"**🖼️ Painting using Enhanced Prompt**:\n{improved_image_prompt}"):
|
|
796
|
+
yield {ChatEvent.STATUS: event}
|
|
796
797
|
|
|
797
798
|
if text_to_image_config.model_type == TextToImageModelConfig.ModelType.OPENAI:
|
|
798
799
|
with timer("Generate image with OpenAI", logger):
|
|
@@ -817,12 +818,14 @@ async def text_to_image(
|
|
|
817
818
|
logger.error(f"Image Generation blocked by OpenAI: {e}")
|
|
818
819
|
status_code = e.status_code # type: ignore
|
|
819
820
|
message = f"Image generation blocked by OpenAI: {e.message}" # type: ignore
|
|
820
|
-
|
|
821
|
+
yield image_url or image, status_code, message, intent_type.value
|
|
822
|
+
return
|
|
821
823
|
else:
|
|
822
824
|
logger.error(f"Image Generation failed with {e}", exc_info=True)
|
|
823
825
|
message = f"Image generation failed with OpenAI error: {e.message}" # type: ignore
|
|
824
826
|
status_code = e.status_code # type: ignore
|
|
825
|
-
|
|
827
|
+
yield image_url or image, status_code, message, intent_type.value
|
|
828
|
+
return
|
|
826
829
|
|
|
827
830
|
elif text_to_image_config.model_type == TextToImageModelConfig.ModelType.STABILITYAI:
|
|
828
831
|
with timer("Generate image with Stability AI", logger):
|
|
@@ -844,7 +847,8 @@ async def text_to_image(
|
|
|
844
847
|
logger.error(f"Image Generation failed with {e}", exc_info=True)
|
|
845
848
|
message = f"Image generation failed with Stability AI error: {e}"
|
|
846
849
|
status_code = e.status_code # type: ignore
|
|
847
|
-
|
|
850
|
+
yield image_url or image, status_code, message, intent_type.value
|
|
851
|
+
return
|
|
848
852
|
|
|
849
853
|
with timer("Convert image to webp", logger):
|
|
850
854
|
# Convert png to webp for faster loading
|
|
@@ -864,7 +868,7 @@ async def text_to_image(
|
|
|
864
868
|
intent_type = ImageIntentType.TEXT_TO_IMAGE_V3
|
|
865
869
|
image = base64.b64encode(webp_image_bytes).decode("utf-8")
|
|
866
870
|
|
|
867
|
-
|
|
871
|
+
yield image_url or image, status_code, improved_image_prompt, intent_type.value
|
|
868
872
|
|
|
869
873
|
|
|
870
874
|
class ApiUserRateLimiter:
|
|
@@ -1186,3 +1190,11 @@ def construct_automation_created_message(automation: Job, crontime: str, query_t
|
|
|
1186
1190
|
|
|
1187
1191
|
Manage your automations [here](/automations).
|
|
1188
1192
|
""".strip()
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
class ChatEvent(Enum):
|
|
1196
|
+
START_LLM_RESPONSE = "start_llm_response"
|
|
1197
|
+
END_LLM_RESPONSE = "end_llm_response"
|
|
1198
|
+
MESSAGE = "message"
|
|
1199
|
+
REFERENCES = "references"
|
|
1200
|
+
STATUS = "status"
|
khoj/routers/indexer.py
CHANGED
|
@@ -60,7 +60,7 @@ async def update(
|
|
|
60
60
|
indexed_data_limiter: ApiIndexedDataLimiter = Depends(
|
|
61
61
|
ApiIndexedDataLimiter(
|
|
62
62
|
incoming_entries_size_limit=10,
|
|
63
|
-
subscribed_incoming_entries_size_limit=
|
|
63
|
+
subscribed_incoming_entries_size_limit=75,
|
|
64
64
|
total_entries_size_limit=10,
|
|
65
65
|
subscribed_total_entries_size_limit=100,
|
|
66
66
|
)
|
khoj/utils/fs_syncer.py
CHANGED
|
@@ -22,7 +22,7 @@ magika = Magika()
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def collect_files(search_type: Optional[SearchType] = SearchType.All, user=None) -> dict:
|
|
25
|
-
files = {}
|
|
25
|
+
files: dict[str, dict] = {"docx": {}, "image": {}}
|
|
26
26
|
|
|
27
27
|
if search_type == SearchType.All or search_type == SearchType.Org:
|
|
28
28
|
org_config = LocalOrgConfig.objects.filter(user=user).first()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: khoj
|
|
3
|
-
Version: 1.16.1.
|
|
3
|
+
Version: 1.16.1.dev47
|
|
4
4
|
Summary: An AI copilot for your Second Brain
|
|
5
5
|
Project-URL: Homepage, https://khoj.dev
|
|
6
6
|
Project-URL: Documentation, https://docs.khoj.dev
|
|
@@ -43,7 +43,7 @@ Requires-Dist: jinja2==3.1.4
|
|
|
43
43
|
Requires-Dist: langchain-community==0.2.5
|
|
44
44
|
Requires-Dist: langchain-openai==0.1.7
|
|
45
45
|
Requires-Dist: langchain==0.2.5
|
|
46
|
-
Requires-Dist: llama-cpp-python==0.2.
|
|
46
|
+
Requires-Dist: llama-cpp-python==0.2.82
|
|
47
47
|
Requires-Dist: lxml==4.9.3
|
|
48
48
|
Requires-Dist: magika~=0.5.1
|
|
49
49
|
Requires-Dist: markdown-it-py~=3.0.0
|
|
@@ -11,7 +11,7 @@ khoj/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
11
11
|
khoj/database/admin.py,sha256=P1zguxSlqnpCvF7CcF8wS9tGCsO3SNDnl6-C_9eyYFA,8814
|
|
12
12
|
khoj/database/apps.py,sha256=pM4tkX5Odw4YW_hLLKK8Nd5kqGddf1en0oMCea44RZw,153
|
|
13
13
|
khoj/database/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
|
14
|
-
khoj/database/adapters/__init__.py,sha256=
|
|
14
|
+
khoj/database/adapters/__init__.py,sha256=KpvAuICVwOz_zUhkqy-2n3xMfvLN-Pm9kqzm-WlI8kY,47525
|
|
15
15
|
khoj/database/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
khoj/database/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
khoj/database/management/commands/change_generated_images_url.py,sha256=w52FwRlyOL4YRpp9O6jJUjSIuGLxVhaS2w1D7gtQgOE,2644
|
|
@@ -87,7 +87,7 @@ khoj/interface/web/404.html,sha256=_WKN17MwiW1b1-8-vx240ZxTO2LmPUh5YnUCaGQpoZk,1
|
|
|
87
87
|
khoj/interface/web/agent.html,sha256=vH3p6gwGlKkNmGO_TSwJMoOvZMvv8t4K8GwaN0QuOAU,9901
|
|
88
88
|
khoj/interface/web/agents.html,sha256=_6WZIYGav87WGJR9QA_UTLESD_itSINuxVOl3ybnRRM,9320
|
|
89
89
|
khoj/interface/web/base_config.html,sha256=vORIYJQ5UzaA3TAMcywRisk-YaaJEwkVAiEJGsbYxvA,12173
|
|
90
|
-
khoj/interface/web/chat.html,sha256=
|
|
90
|
+
khoj/interface/web/chat.html,sha256=B8Hpb9dwcHEXMC5tSyZc3945IkWCOwjWC2zcatflh5Y,149819
|
|
91
91
|
khoj/interface/web/config.html,sha256=8Ge79FbYfWLovc_u8XVkCDGFjK7ZqlRFI1hHI_Z2KWs,46026
|
|
92
92
|
khoj/interface/web/config_automation.html,sha256=B_-uUBi-uVlhPqFNsxxNdp-m0BGST0maqJ1qTzfkkzA,46095
|
|
93
93
|
khoj/interface/web/content_source_computer_input.html,sha256=FzJbF1XpOF2HV6C1l0iKiU4LdRtMa5T0ETSuLyC7PPM,5983
|
|
@@ -184,33 +184,33 @@ khoj/processor/content/pdf/pdf_to_entries.py,sha256=wGXSmxifrjRE9eJWoFokI0G66kyM
|
|
|
184
184
|
khoj/processor/content/plaintext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
185
185
|
khoj/processor/content/plaintext/plaintext_to_entries.py,sha256=4JpWWulSjzrYsGNLPt7Z0qZykjU6isF58vx-0RJjQRw,5127
|
|
186
186
|
khoj/processor/conversation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
187
|
-
khoj/processor/conversation/prompts.py,sha256=
|
|
188
|
-
khoj/processor/conversation/utils.py,sha256=
|
|
187
|
+
khoj/processor/conversation/prompts.py,sha256=8X0FzJ8iZR0lTdNtCv0WmGPTm4EyP-YZiKJsluZkC9g,32086
|
|
188
|
+
khoj/processor/conversation/utils.py,sha256=_uWu1nxcY-Cv2ip-TBdyqepUkMYhijvzjnproumvzXk,10586
|
|
189
189
|
khoj/processor/conversation/anthropic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
190
|
-
khoj/processor/conversation/anthropic/anthropic_chat.py,sha256=
|
|
190
|
+
khoj/processor/conversation/anthropic/anthropic_chat.py,sha256=7yBlY26PNI4wzwHph4TTQ_tJlLmoNjiXyhzHPJeUVmI,7887
|
|
191
191
|
khoj/processor/conversation/anthropic/utils.py,sha256=uc9d_gIk4Ux2NRlkw3FP9L9KeLRoUI7nC_qb2Qp6d_4,3253
|
|
192
192
|
khoj/processor/conversation/offline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
193
|
-
khoj/processor/conversation/offline/chat_model.py,sha256=
|
|
194
|
-
khoj/processor/conversation/offline/utils.py,sha256
|
|
193
|
+
khoj/processor/conversation/offline/chat_model.py,sha256=7OIexLDXfdyF2jk-JFMqojNW-grlc2jtCt1zxCO-VAY,9349
|
|
194
|
+
khoj/processor/conversation/offline/utils.py,sha256=n2T3vwAIZnSe9-UN1VORLPrLEUcamXXE9isL2ie-9R8,3033
|
|
195
195
|
khoj/processor/conversation/offline/whisper.py,sha256=DJI-8y8DULO2cQ49m2VOvRyIZ2TxBypc15gM8O3HuMI,470
|
|
196
196
|
khoj/processor/conversation/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
197
|
-
khoj/processor/conversation/openai/gpt.py,sha256=
|
|
197
|
+
khoj/processor/conversation/openai/gpt.py,sha256=bbEyiOeRgko65bLsFHNlkMw1cvbiawQsjmDipCpy0E4,7111
|
|
198
198
|
khoj/processor/conversation/openai/utils.py,sha256=UCfu-dHnkgcKxMajUaWnlxW5Zdidqecv5jIdmimie6o,4067
|
|
199
199
|
khoj/processor/conversation/openai/whisper.py,sha256=RuwDtxSJrVWYdZz4aVnk0XiMQy9w8W9lFcVfE0hMiFY,432
|
|
200
200
|
khoj/processor/speech/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
201
201
|
khoj/processor/speech/text_to_speech.py,sha256=Q7sapi5Hv6woXOumtrGqR0t6izZrFBkWXFOGrHM6dJ4,1929
|
|
202
202
|
khoj/processor/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
203
|
-
khoj/processor/tools/online_search.py,sha256=
|
|
203
|
+
khoj/processor/tools/online_search.py,sha256=3qVHg3oU7nU3O2MFG9M6PsdXNusp_B4oTSTIpxN_oLc,9640
|
|
204
204
|
khoj/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
205
|
-
khoj/routers/api.py,sha256=
|
|
205
|
+
khoj/routers/api.py,sha256=simxuuN0ro2JtWnNg7qZX1ZoNzZdL5Zvz3MKhL3sM5I,23823
|
|
206
206
|
khoj/routers/api_agents.py,sha256=A8gS-LIgg5cjV9Ec7P-TgCmmylaNtT43TqXcxIia3PQ,1443
|
|
207
|
-
khoj/routers/api_chat.py,sha256=
|
|
207
|
+
khoj/routers/api_chat.py,sha256=yyhs22HLeqDkd7gEE0LgwZ2pGvuxt-KwL5o7umwDRLA,36232
|
|
208
208
|
khoj/routers/api_config.py,sha256=qK4he5cH-Rdx5WagOOfoNRpHuJUoD8ja4zbl0ksBh9M,13446
|
|
209
209
|
khoj/routers/api_phone.py,sha256=p9yfc4WeMHDC0hg3aQk60a2VBy8rZPdEnz9wdJ7DzkU,2208
|
|
210
210
|
khoj/routers/auth.py,sha256=pCOLSRihJWcn097DRPxLjPdlejsjHJFRs9jHIzLujZU,6247
|
|
211
211
|
khoj/routers/email.py,sha256=hhxyLdmgSUfeHTXTco7g4aWDAEaVzF82mV-hshxzHsg,3695
|
|
212
|
-
khoj/routers/helpers.py,sha256=
|
|
213
|
-
khoj/routers/indexer.py,sha256=
|
|
212
|
+
khoj/routers/helpers.py,sha256=xVE3ZQl5A0HC64OYekl1GSATpf0LrBraxGAGBqP7XR8,47617
|
|
213
|
+
khoj/routers/indexer.py,sha256=CnXbxJ5ZCBBuNvJalGyMNFa4FBa47loEjSiPz_KjMhQ,12560
|
|
214
214
|
khoj/routers/notion.py,sha256=DaEvbBLqg0F7UArRalKZqzvl0fxW7snShByo-BOyRO8,3137
|
|
215
215
|
khoj/routers/storage.py,sha256=9ZfBsr_omxdFV-Lcj6p30xTQcF_7wwCZ9XFJukzjITE,1429
|
|
216
216
|
khoj/routers/subscription.py,sha256=qEyV7m7mrY6MGtaij8W3v61tpzX2a7ydm2B-E8h_R-M,4285
|
|
@@ -227,7 +227,7 @@ khoj/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
227
227
|
khoj/utils/cli.py,sha256=oTDt6ClKvYNJ3_j9Omwx49H03IxC7sq4oL1qFpormWc,3456
|
|
228
228
|
khoj/utils/config.py,sha256=ZNVZjyJhd7KmeKCA1a1Dtns2ghhAtZtsCF9Lsm-gilw,1805
|
|
229
229
|
khoj/utils/constants.py,sha256=vtQx9UTXwFrZdgdEWudTYMEDxecXP5g2rRYWYIMAsdU,856
|
|
230
|
-
khoj/utils/fs_syncer.py,sha256=
|
|
230
|
+
khoj/utils/fs_syncer.py,sha256=A_ME2w5O7RRzku06CrM3NBY7QakkgfGV62CUuIeRjMs,9930
|
|
231
231
|
khoj/utils/helpers.py,sha256=b7q_aQw52C_CO9y18KWRD2Z1Oyo9E6Ef7F9_jfi5S00,14041
|
|
232
232
|
khoj/utils/initialization.py,sha256=Q8csjz5YqQ7WZ6mYJWvmp_Dh36dFRpZ3WRWxEgT2Ql0,7117
|
|
233
233
|
khoj/utils/jsonl.py,sha256=0Ac_COqr8sLCXntzZtquxuCEVRM2c3yKeDRGhgOBRpQ,1192
|
|
@@ -235,8 +235,8 @@ khoj/utils/models.py,sha256=Q5tcC9-z25sCiub048fLnvZ6_IIO1bcPNxt5payekk0,2009
|
|
|
235
235
|
khoj/utils/rawconfig.py,sha256=iqyidXyM4AM6QAPLLMFrMuYR6dYplj374UBNFDOBwkY,3892
|
|
236
236
|
khoj/utils/state.py,sha256=x4GTewP1YhOA6c_32N4wOjnV-3AA3xG_qbY1-wC2Uxc,1559
|
|
237
237
|
khoj/utils/yaml.py,sha256=H0mfw0ZvBFUvFmCQn8pWkfxdmIebsrSykza7D8Wv6wQ,1430
|
|
238
|
-
khoj-1.16.1.
|
|
239
|
-
khoj-1.16.1.
|
|
240
|
-
khoj-1.16.1.
|
|
241
|
-
khoj-1.16.1.
|
|
242
|
-
khoj-1.16.1.
|
|
238
|
+
khoj-1.16.1.dev47.dist-info/METADATA,sha256=-bQLRCGiG5DM8ByuoW0zZ5dqoyN3T9vOFhDpHai88uw,6894
|
|
239
|
+
khoj-1.16.1.dev47.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
240
|
+
khoj-1.16.1.dev47.dist-info/entry_points.txt,sha256=KBIcez5N_jCgq_ER4Uxf-e1lxTBMTE_BBjMwwfeZyAg,39
|
|
241
|
+
khoj-1.16.1.dev47.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
242
|
+
khoj-1.16.1.dev47.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|