khoj 1.17.0__py3-none-any.whl → 1.17.1.dev217__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 (46) hide show
  1. khoj/configure.py +6 -6
  2. khoj/database/adapters/__init__.py +47 -2
  3. khoj/database/migrations/0053_agent_style_color_agent_style_icon.py +61 -0
  4. khoj/database/models/__init__.py +35 -0
  5. khoj/interface/web/assets/icons/favicon-128x128.png +0 -0
  6. khoj/interface/web/assets/icons/favicon-256x256.png +0 -0
  7. khoj/interface/web/assets/icons/khoj-logo-sideways-200.png +0 -0
  8. khoj/interface/web/assets/icons/khoj-logo-sideways-500.png +0 -0
  9. khoj/interface/web/assets/icons/khoj-logo-sideways.svg +31 -5384
  10. khoj/interface/web/assets/icons/khoj.svg +26 -0
  11. khoj/interface/web/chat.html +5 -5
  12. khoj/interface/web/content_source_computer_input.html +3 -3
  13. khoj/interface/web/content_source_github_input.html +1 -1
  14. khoj/interface/web/content_source_notion_input.html +1 -1
  15. khoj/interface/web/public_conversation.html +1 -1
  16. khoj/interface/web/search.html +2 -2
  17. khoj/interface/web/{config.html → settings.html} +30 -30
  18. khoj/interface/web/utils.html +1 -1
  19. khoj/processor/content/docx/docx_to_entries.py +4 -9
  20. khoj/processor/content/github/github_to_entries.py +1 -3
  21. khoj/processor/content/images/image_to_entries.py +4 -9
  22. khoj/processor/content/markdown/markdown_to_entries.py +4 -9
  23. khoj/processor/content/notion/notion_to_entries.py +1 -3
  24. khoj/processor/content/org_mode/org_to_entries.py +4 -9
  25. khoj/processor/content/pdf/pdf_to_entries.py +4 -9
  26. khoj/processor/content/plaintext/plaintext_to_entries.py +4 -9
  27. khoj/processor/content/text_to_entries.py +1 -3
  28. khoj/processor/tools/online_search.py +4 -4
  29. khoj/routers/api.py +49 -4
  30. khoj/routers/api_agents.py +3 -1
  31. khoj/routers/api_chat.py +80 -88
  32. khoj/routers/api_content.py +538 -0
  33. khoj/routers/api_model.py +156 -0
  34. khoj/routers/helpers.py +308 -7
  35. khoj/routers/notion.py +2 -8
  36. khoj/routers/web_client.py +43 -256
  37. khoj/search_type/text_search.py +5 -4
  38. khoj/utils/fs_syncer.py +3 -1
  39. khoj/utils/rawconfig.py +6 -1
  40. {khoj-1.17.0.dist-info → khoj-1.17.1.dev217.dist-info}/METADATA +2 -2
  41. {khoj-1.17.0.dist-info → khoj-1.17.1.dev217.dist-info}/RECORD +44 -42
  42. khoj/routers/api_config.py +0 -434
  43. khoj/routers/indexer.py +0 -349
  44. {khoj-1.17.0.dist-info → khoj-1.17.1.dev217.dist-info}/WHEEL +0 -0
  45. {khoj-1.17.0.dist-info → khoj-1.17.1.dev217.dist-info}/entry_points.txt +0 -0
  46. {khoj-1.17.0.dist-info → khoj-1.17.1.dev217.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,5 @@
1
1
  khoj/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- khoj/configure.py,sha256=C3F3g2rbBKnXLeHvQvak3Te2XkaQOXL6x8-iE_u9PxQ,17319
2
+ khoj/configure.py,sha256=Il9hwCHnsbS8P8anjzJA5PjbuYY2-_ZrJB3_woA1cwA,17323
3
3
  khoj/main.py,sha256=58Rssq2H5AM69dA2UyGHye3vPAMp5RRS6xLcGkB_G_w,8147
4
4
  khoj/manage.py,sha256=njo6uLxGaMamTPesHjFEOIBJbpIUrz39e1V59zKj544,664
5
5
  khoj/app/README.md,sha256=PSQjKCdpU2hgszLVF8yEhV7TWhbEEb-1aYLTRuuAsKI,2832
@@ -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=KpvAuICVwOz_zUhkqy-2n3xMfvLN-Pm9kqzm-WlI8kY,47525
14
+ khoj/database/adapters/__init__.py,sha256=XLIW0juq4tcwaf5aakqoEOgYH1Mb5MjZCNK3Tky7l8A,49663
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
@@ -77,8 +77,9 @@ khoj/database/migrations/0049_texttoimagemodelconfig_api_key_and_more.py,sha256=
77
77
  khoj/database/migrations/0050_alter_processlock_name.py,sha256=_Uh-L-zjDMFdTRMS0nz4BKotyt9RvIoHPZ5RqjJrLk0,659
78
78
  khoj/database/migrations/0051_merge_20240702_1220.py,sha256=K6VNV-way0b4aMtyPwaEmoAEZUCIrj6Xoekn9yirBEw,331
79
79
  khoj/database/migrations/0052_alter_searchmodelconfig_bi_encoder_docs_encode_config_and_more.py,sha256=ITNgRgz4Oh9WgJG9WFztGXIPnMbCP4LJCC7jZA6uC_c,824
80
+ khoj/database/migrations/0053_agent_style_color_agent_style_icon.py,sha256=j30FqSaRJYiDXlFdip7Nslw3OZZWkymQbcV4yie1hbk,2054
80
81
  khoj/database/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
- khoj/database/models/__init__.py,sha256=u3tYfB7Kf6TuoFhFD7u987q3-GWX-6tAFQQNA0b-4xk,17641
82
+ khoj/database/models/__init__.py,sha256=zEYw54qV2lD0grXPwOM5NpoMb0-mHN0PuKKNtGw8raQ,18746
82
83
  khoj/interface/email/feedback.html,sha256=xksuPFamx4hGWyTTxZKRgX_eiYQQEuv-eK9Xmkt-nwU,1216
83
84
  khoj/interface/email/magic_link.html,sha256=jXY_2hD3o15Ns5UDzbjLT8FHBnZiS7jo38YkYXIS-4w,947
84
85
  khoj/interface/email/task.html,sha256=yXywzC-5P4nXbhqvgCmwcCpTRbD5eWuDXMpgYSotztM,3311
@@ -87,17 +88,17 @@ khoj/interface/web/404.html,sha256=_WKN17MwiW1b1-8-vx240ZxTO2LmPUh5YnUCaGQpoZk,1
87
88
  khoj/interface/web/agent.html,sha256=vH3p6gwGlKkNmGO_TSwJMoOvZMvv8t4K8GwaN0QuOAU,9901
88
89
  khoj/interface/web/agents.html,sha256=_6WZIYGav87WGJR9QA_UTLESD_itSINuxVOl3ybnRRM,9320
89
90
  khoj/interface/web/base_config.html,sha256=vORIYJQ5UzaA3TAMcywRisk-YaaJEwkVAiEJGsbYxvA,12173
90
- khoj/interface/web/chat.html,sha256=B8Hpb9dwcHEXMC5tSyZc3945IkWCOwjWC2zcatflh5Y,149819
91
- khoj/interface/web/config.html,sha256=8Ge79FbYfWLovc_u8XVkCDGFjK7ZqlRFI1hHI_Z2KWs,46026
91
+ khoj/interface/web/chat.html,sha256=0qLswm0SOQJ2ZbNOy968Mc9g14Lq0vYtF5zDIAeS0d8,149786
92
92
  khoj/interface/web/config_automation.html,sha256=B_-uUBi-uVlhPqFNsxxNdp-m0BGST0maqJ1qTzfkkzA,46095
93
- khoj/interface/web/content_source_computer_input.html,sha256=FzJbF1XpOF2HV6C1l0iKiU4LdRtMa5T0ETSuLyC7PPM,5983
94
- khoj/interface/web/content_source_github_input.html,sha256=OTmcALYFyc7ZQPNQ-X4RROSH6HoqsHH4B0_hC5PkTzc,8268
95
- khoj/interface/web/content_source_notion_input.html,sha256=qlIXBMvABqBq4OTFX310U-WkvAYBUA2dU-mAKE2Jqzo,3668
93
+ khoj/interface/web/content_source_computer_input.html,sha256=PGtEmmsAc0g0DQM5sNlvC5SexGzmn5aC6HYUvm3qr54,5956
94
+ khoj/interface/web/content_source_github_input.html,sha256=YpsLBpsATW08ttrGysqktx2EczC4nebKlvWpwxtwmFY,8249
95
+ khoj/interface/web/content_source_notion_input.html,sha256=0GB_q2uVQHLrz5dIT18LpzVcb-1LdbFlIUprxeZJgUk,3649
96
96
  khoj/interface/web/khoj.webmanifest,sha256=G_Aphzn6SMaY73AYLCD12mgztZvagh_U2YpkjQXIY1U,1628
97
97
  khoj/interface/web/login.html,sha256=U3rb0bZg06-dcR6swB-Ho33DX8V9-cqa-70yPIj8pKY,6838
98
- khoj/interface/web/public_conversation.html,sha256=0XGJ4LmiO9DuhSg72it6XDVadl2ANih1UI0QMK6aiKQ,76256
99
- khoj/interface/web/search.html,sha256=unQYiPNpz2gLQOieLeGkAG6qLsO56-kKd787zh3wbII,18326
100
- khoj/interface/web/utils.html,sha256=rm2_ylTNloxeEBYFMK_22EfbFgvybooy1HJEhZrSzOQ,3141
98
+ khoj/interface/web/public_conversation.html,sha256=tMmjO2Dz6Wcn83uTn_zvEg8yz_NNeuo_Jhv_vCO8JJ4,76251
99
+ khoj/interface/web/search.html,sha256=vEgN-SHWuK6arArgvIn5uetsCb4tN2i19CWCr-p7Z0U,18329
100
+ khoj/interface/web/settings.html,sha256=rVqlMrsxlXeH0oAKZwMn902nNICpwlVkdklfHLsUnxk,45908
101
+ khoj/interface/web/utils.html,sha256=_UrcCvSkx1SAzhlTsvrj9LFlnJuJ-_cMtz6HY-rEIkI,3143
101
102
  khoj/interface/web/assets/khoj.css,sha256=rhW8-RwvkpTC5GbtBt0EByaXaHjlxpxPYxrUuzMWDC0,5659
102
103
  khoj/interface/web/assets/markdown-it.min.js,sha256=zu3EiJi63wq7KFBdLv3zrWI2enxgn3Ia-IKhWlTDIco,275822
103
104
  khoj/interface/web/assets/natural-cron.min.js,sha256=sck3Rmq6AUapLuBwj4A516n_BYQ2eNEICgQzwS83s0A,15760
@@ -119,14 +120,15 @@ khoj/interface/web/assets/icons/delete.svg,sha256=wgVI_WiV_cGEsNg8DWUEhnu5DkjkWe
119
120
  khoj/interface/web/assets/icons/docx.svg,sha256=o_WbsAvXgaKAsNMwY3VaEeUvmxzjqEt4fRvcna8rS2Q,1325
120
121
  khoj/interface/web/assets/icons/edit.svg,sha256=7aaMUYte2aSC3XsYMwzjx2pST1Bt34gLmiqA9N_aZ6A,571
121
122
  khoj/interface/web/assets/icons/favicon-128x128.ico,sha256=JMZf9aZor9AUbh5kuFNDaG3Mjxvoau5k80yRA9ly5TQ,205167
122
- khoj/interface/web/assets/icons/favicon-128x128.png,sha256=7pLHyK4cdLKMseot5BCW4fSiMsT2VHZtfyP3um6bV1Q,12518
123
- khoj/interface/web/assets/icons/favicon-256x256.png,sha256=hVJpnfjYbjO6Bo0v4J_3zCp-EfVpgLc7GK1CzOv-reI,30234
123
+ khoj/interface/web/assets/icons/favicon-128x128.png,sha256=aTxivDb3CYyThkVZWz8A19xl_dNut5DbkXhODWF3A9Q,5640
124
+ khoj/interface/web/assets/icons/favicon-256x256.png,sha256=xPCMLHiaL7lYOdQLZrKwWE-Qjn5ZaysSZB0ScYv4UZU,12312
124
125
  khoj/interface/web/assets/icons/favicon.icns,sha256=34h6qrRMdzx16_d5Cy3zGMKXxztyWxmZjhfRR6oN3Fw,31531
125
126
  khoj/interface/web/assets/icons/github.svg,sha256=E789GwMweG0aU1wJNp0FjWHlFX1AxuA5H0durEnw5hQ,964
126
127
  khoj/interface/web/assets/icons/key.svg,sha256=ePgqDcsgBhIX6stfcDRlMkNMCggcRp8uoHtONqjj4X0,1100
127
- khoj/interface/web/assets/icons/khoj-logo-sideways-200.png,sha256=pFZFcavWwkN4Kdg9d9ZsVFwbEVedYUuWNChaRHXyLXA,13011
128
- khoj/interface/web/assets/icons/khoj-logo-sideways-500.png,sha256=brCp0b1oFTT1CE0gt_J_oU44OfSH5wQxljYuRmVYF_k,29856
129
- khoj/interface/web/assets/icons/khoj-logo-sideways.svg,sha256=O2lzKcRxWWMjtkRpNnuO96KIAeKf3GfAL-Xi0CKtYPk,1301428
128
+ khoj/interface/web/assets/icons/khoj-logo-sideways-200.png,sha256=2_F1PpTZzfjvaHej9jjENx03H1vKtFsVkolwTPLJP9Q,6637
129
+ khoj/interface/web/assets/icons/khoj-logo-sideways-500.png,sha256=VQsQ20NC-sKYHa9UgAvLM2N25DWRISZUIGW0zhnRres,18603
130
+ khoj/interface/web/assets/icons/khoj-logo-sideways.svg,sha256=wLU1lBtzZMQNUS5maD0-vqY1q4D0vuqWnRmIUy7odk4,14772
131
+ khoj/interface/web/assets/icons/khoj.svg,sha256=8QZ0q3vazgY0aGhTT9Um432GbwtY1Vn64vxvAfoSwaI,7967
130
132
  khoj/interface/web/assets/icons/logotype.svg,sha256=diy7UEKDBv9dFtGfE8Y5gf9JTdQUKTnq_dSdC2RGVIA,4031
131
133
  khoj/interface/web/assets/icons/markdown.svg,sha256=ngHbtxRmKcMVHv8NgscjS-azYp4hgzYQl2g0oGzYSTg,283
132
134
  khoj/interface/web/assets/icons/new.svg,sha256=pq1O8z7aMhDmWA8kKGLT5RPOpNu16ZOsQfmUdaVWMXs,949
@@ -166,23 +168,23 @@ khoj/migrations/migrate_version.py,sha256=6CTsLuxiLnFVF8A7CjsIz3PcnJd8fAOZeIx6tT
166
168
  khoj/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
169
  khoj/processor/embeddings.py,sha256=80irR_-dxQJ3LVTGUgaC1QyyCqyJ2CDUZ131u_rDLA0,5149
168
170
  khoj/processor/content/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
- khoj/processor/content/text_to_entries.py,sha256=WWm4cixlFvYswwT3f0Z3OxRyq1jmunKIFEYjE_Y1zVk,14577
171
+ khoj/processor/content/text_to_entries.py,sha256=Oa4Ny8c5S1_IGCmjCtUI45hX1fPTRwxXhHg1lHFqHy8,14537
170
172
  khoj/processor/content/docx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
- khoj/processor/content/docx/docx_to_entries.py,sha256=I_2rtreAFYRViwZInrOsUsQyGYZaJirNocKfUasyiVk,4466
173
+ khoj/processor/content/docx/docx_to_entries.py,sha256=qCVbvetCDG30lxxUeEjg_BTNJtlYmCHZ1qDH0sBSkqk,4333
172
174
  khoj/processor/content/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
173
- khoj/processor/content/github/github_to_entries.py,sha256=7i8VSx41cTOUVaSe1fz-6mhIURgflBiUerHHJrej1TI,9927
175
+ khoj/processor/content/github/github_to_entries.py,sha256=SfgXJi59LvFldnRLC5dJ3tUhM5vym-ZrbUovh1G42LQ,9887
174
176
  khoj/processor/content/images/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
175
- khoj/processor/content/images/image_to_entries.py,sha256=T8wfV9RS8Qs5eefYG4UWXy-KS7mSiFE4QAvir2XGv80,5036
177
+ khoj/processor/content/images/image_to_entries.py,sha256=_SEOfXUMNyTFbDFSLoAAE-GXpmtV_dgJ7_KuzQN8sLs,4903
176
178
  khoj/processor/content/markdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
177
- khoj/processor/content/markdown/markdown_to_entries.py,sha256=WW3Jlk8QrOgkPi3UIRY4oMkWAFQEXfjASF8gxASQtts,7209
178
- khoj/processor/content/notion/notion_to_entries.py,sha256=dyYZUsltBGpBfVU8Z7MBe7tZtdnSzIypOVVHFI8_FnQ,9869
179
+ khoj/processor/content/markdown/markdown_to_entries.py,sha256=3ZXkJtehcVcMrNY6V4p-8i53zDIIsiVGQg-AMtD_U1U,7076
180
+ khoj/processor/content/notion/notion_to_entries.py,sha256=zCcajTp60ieJExiX6Qwfctm_DR__bRRJgUXh47jjOac,9829
179
181
  khoj/processor/content/org_mode/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
180
- khoj/processor/content/org_mode/org_to_entries.py,sha256=3rj4i9TugExndJxux5JfaBAt6aHNHhOMfNpg7QFrL5M,10384
182
+ khoj/processor/content/org_mode/org_to_entries.py,sha256=UYlCJRaNwwuf9LobiprVSGECOOyNV0q3R1kVnmOdvE8,10251
181
183
  khoj/processor/content/org_mode/orgnode.py,sha256=C0j0e6iHAY3bKBIcM9PaytqoR9dQ1Qd6hNHzMN-Zeg0,18476
182
184
  khoj/processor/content/pdf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
- khoj/processor/content/pdf/pdf_to_entries.py,sha256=wGXSmxifrjRE9eJWoFokI0G66kyMmvoog7HFLYyADBA,5044
185
+ khoj/processor/content/pdf/pdf_to_entries.py,sha256=OE90osFchohih3RYvDmZepbtzWoGJRdgW-KdqSd2rG8,4911
184
186
  khoj/processor/content/plaintext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
185
- khoj/processor/content/plaintext/plaintext_to_entries.py,sha256=4JpWWulSjzrYsGNLPt7Z0qZykjU6isF58vx-0RJjQRw,5127
187
+ khoj/processor/content/plaintext/plaintext_to_entries.py,sha256=97i7Cm0DTY7jW4iqKOT_oVc2ooa_XhQ8iImsljp1Kek,4994
186
188
  khoj/processor/conversation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
187
189
  khoj/processor/conversation/prompts.py,sha256=8X0FzJ8iZR0lTdNtCv0WmGPTm4EyP-YZiKJsluZkC9g,32086
188
190
  khoj/processor/conversation/utils.py,sha256=_uWu1nxcY-Cv2ip-TBdyqepUkMYhijvzjnproumvzXk,10586
@@ -200,43 +202,43 @@ khoj/processor/conversation/openai/whisper.py,sha256=RuwDtxSJrVWYdZz4aVnk0XiMQy9
200
202
  khoj/processor/speech/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
201
203
  khoj/processor/speech/text_to_speech.py,sha256=Q7sapi5Hv6woXOumtrGqR0t6izZrFBkWXFOGrHM6dJ4,1929
202
204
  khoj/processor/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
- khoj/processor/tools/online_search.py,sha256=3qVHg3oU7nU3O2MFG9M6PsdXNusp_B4oTSTIpxN_oLc,9640
205
+ khoj/processor/tools/online_search.py,sha256=cQZ6Aw7Kg0QXCthK4Vdn3gtF2K9GtUZmCkbxWYC_hJw,9620
204
206
  khoj/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
205
- khoj/routers/api.py,sha256=simxuuN0ro2JtWnNg7qZX1ZoNzZdL5Zvz3MKhL3sM5I,23823
206
- khoj/routers/api_agents.py,sha256=A8gS-LIgg5cjV9Ec7P-TgCmmylaNtT43TqXcxIia3PQ,1443
207
- khoj/routers/api_chat.py,sha256=yyhs22HLeqDkd7gEE0LgwZ2pGvuxt-KwL5o7umwDRLA,36232
208
- khoj/routers/api_config.py,sha256=qK4he5cH-Rdx5WagOOfoNRpHuJUoD8ja4zbl0ksBh9M,13446
207
+ khoj/routers/api.py,sha256=Zbr81RHU00SQxRbbFlYM_gT81oLb3lAXoksj-I1-pPg,25066
208
+ khoj/routers/api_agents.py,sha256=ks8QzjmZiio6j1QGi6xFtDmVxd9lvC6LPB-WcDPnF8o,1525
209
+ khoj/routers/api_chat.py,sha256=jtL77XyqN6GoOsXjoekMJJWmddb5qx79eu09gRLVLkw,35928
210
+ khoj/routers/api_content.py,sha256=OfY05ggRmg0FuVWzodBfV_5Gc6UbGCfchiIk8eqKA2o,17387
211
+ khoj/routers/api_model.py,sha256=5m7JWwgd9jILiLivRu7NEyY2E-tUkqoEkGg6j6uM1g0,4646
209
212
  khoj/routers/api_phone.py,sha256=p9yfc4WeMHDC0hg3aQk60a2VBy8rZPdEnz9wdJ7DzkU,2208
210
213
  khoj/routers/auth.py,sha256=pCOLSRihJWcn097DRPxLjPdlejsjHJFRs9jHIzLujZU,6247
211
214
  khoj/routers/email.py,sha256=hhxyLdmgSUfeHTXTco7g4aWDAEaVzF82mV-hshxzHsg,3695
212
- khoj/routers/helpers.py,sha256=xVE3ZQl5A0HC64OYekl1GSATpf0LrBraxGAGBqP7XR8,47617
213
- khoj/routers/indexer.py,sha256=CnXbxJ5ZCBBuNvJalGyMNFa4FBa47loEjSiPz_KjMhQ,12560
214
- khoj/routers/notion.py,sha256=DaEvbBLqg0F7UArRalKZqzvl0fxW7snShByo-BOyRO8,3137
215
+ khoj/routers/helpers.py,sha256=UK_0pliNZhh2BMacHraNZlxTbesN6gwK9FqV4NcEcQY,59740
216
+ khoj/routers/notion.py,sha256=0iG_DPVjg8n_LBWGHA8M6eHnJJDL-isARSEHTYStz6c,2809
215
217
  khoj/routers/storage.py,sha256=9ZfBsr_omxdFV-Lcj6p30xTQcF_7wwCZ9XFJukzjITE,1429
216
218
  khoj/routers/subscription.py,sha256=qEyV7m7mrY6MGtaij8W3v61tpzX2a7ydm2B-E8h_R-M,4285
217
219
  khoj/routers/twilio.py,sha256=MLsuCm4--ETvr3sLxbF0CL_ehlg_l2rKBSLR2Qh2Xls,1081
218
- khoj/routers/web_client.py,sha256=60N5PqGtVg50p47R5RPMYeLm-S_oQCsPUzjKpDjDCR8,17580
220
+ khoj/routers/web_client.py,sha256=QraT0eCf7nTqsshSFBP5fWIfisZofk5xVB-818zZLgU,9014
219
221
  khoj/search_filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
220
222
  khoj/search_filter/base_filter.py,sha256=BzoZA_wAUg_eZ5vhaaipwVTSG0ZMxWCHxHsZrzo4KS0,358
221
223
  khoj/search_filter/date_filter.py,sha256=4VL63kDVqYKFOzkCeV6R8Z8lxFaAbbn_z_RWaWQNDWY,10103
222
224
  khoj/search_filter/file_filter.py,sha256=1b6xgFqBNB6ZvQFbEXERdTEYV6PDxfHpUVbnz3aFaws,939
223
225
  khoj/search_filter/word_filter.py,sha256=5Yx95aSiqGke9kEIbp8T-Ak4dS9cTd3VxI1SaJoK1wY,1005
224
226
  khoj/search_type/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
225
- khoj/search_type/text_search.py,sha256=Sj55WCTDAZ1j1-dsL-UOSKz52XzLeaCoMRtfT3ecl4Q,8953
227
+ khoj/search_type/text_search.py,sha256=AEDBbkjMwDieDiz6_Bdaoq0cywIova1Uz6V1O-XRldQ,8939
226
228
  khoj/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
227
229
  khoj/utils/cli.py,sha256=oTDt6ClKvYNJ3_j9Omwx49H03IxC7sq4oL1qFpormWc,3456
228
230
  khoj/utils/config.py,sha256=ZNVZjyJhd7KmeKCA1a1Dtns2ghhAtZtsCF9Lsm-gilw,1805
229
231
  khoj/utils/constants.py,sha256=vtQx9UTXwFrZdgdEWudTYMEDxecXP5g2rRYWYIMAsdU,856
230
- khoj/utils/fs_syncer.py,sha256=A_ME2w5O7RRzku06CrM3NBY7QakkgfGV62CUuIeRjMs,9930
232
+ khoj/utils/fs_syncer.py,sha256=bQgcbYYC3x11RyCqI_kUzzqGpcKTodGgdT-3OTQsXqw,9977
231
233
  khoj/utils/helpers.py,sha256=b7q_aQw52C_CO9y18KWRD2Z1Oyo9E6Ef7F9_jfi5S00,14041
232
234
  khoj/utils/initialization.py,sha256=Q8csjz5YqQ7WZ6mYJWvmp_Dh36dFRpZ3WRWxEgT2Ql0,7117
233
235
  khoj/utils/jsonl.py,sha256=0Ac_COqr8sLCXntzZtquxuCEVRM2c3yKeDRGhgOBRpQ,1192
234
236
  khoj/utils/models.py,sha256=Q5tcC9-z25sCiub048fLnvZ6_IIO1bcPNxt5payekk0,2009
235
- khoj/utils/rawconfig.py,sha256=iqyidXyM4AM6QAPLLMFrMuYR6dYplj374UBNFDOBwkY,3892
237
+ khoj/utils/rawconfig.py,sha256=luk7Vb_ODuoTdMd_IG-yVXGoyoU-RktyapBG5D1N_VI,3985
236
238
  khoj/utils/state.py,sha256=x4GTewP1YhOA6c_32N4wOjnV-3AA3xG_qbY1-wC2Uxc,1559
237
239
  khoj/utils/yaml.py,sha256=H0mfw0ZvBFUvFmCQn8pWkfxdmIebsrSykza7D8Wv6wQ,1430
238
- khoj-1.17.0.dist-info/METADATA,sha256=PqC1QZ0mxHuSjXTK4Q3Ya1dFsSYJM8jBeX3ah8l_cpY,6888
239
- khoj-1.17.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
240
- khoj-1.17.0.dist-info/entry_points.txt,sha256=KBIcez5N_jCgq_ER4Uxf-e1lxTBMTE_BBjMwwfeZyAg,39
241
- khoj-1.17.0.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
242
- khoj-1.17.0.dist-info/RECORD,,
240
+ khoj-1.17.1.dev217.dist-info/METADATA,sha256=IFUoA-XNLJB5P9-pKK__hzLhjI6DHducu71CyNnXTRI,6877
241
+ khoj-1.17.1.dev217.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
242
+ khoj-1.17.1.dev217.dist-info/entry_points.txt,sha256=KBIcez5N_jCgq_ER4Uxf-e1lxTBMTE_BBjMwwfeZyAg,39
243
+ khoj-1.17.1.dev217.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
244
+ khoj-1.17.1.dev217.dist-info/RECORD,,
@@ -1,434 +0,0 @@
1
- import json
2
- import logging
3
- import math
4
- from typing import Dict, List, Optional, Union
5
-
6
- from asgiref.sync import sync_to_async
7
- from fastapi import APIRouter, HTTPException, Request
8
- from fastapi.requests import Request
9
- from fastapi.responses import Response
10
- from starlette.authentication import has_required_scope, requires
11
-
12
- from khoj.database import adapters
13
- from khoj.database.adapters import ConversationAdapters, EntryAdapters
14
- from khoj.database.models import Entry as DbEntry
15
- from khoj.database.models import (
16
- GithubConfig,
17
- KhojUser,
18
- LocalMarkdownConfig,
19
- LocalOrgConfig,
20
- LocalPdfConfig,
21
- LocalPlaintextConfig,
22
- NotionConfig,
23
- Subscription,
24
- )
25
- from khoj.routers.helpers import CommonQueryParams, update_telemetry_state
26
- from khoj.utils import constants, state
27
- from khoj.utils.rawconfig import (
28
- FullConfig,
29
- GithubContentConfig,
30
- NotionContentConfig,
31
- SearchConfig,
32
- )
33
- from khoj.utils.state import SearchType
34
-
35
- api_config = APIRouter()
36
- logger = logging.getLogger(__name__)
37
-
38
-
39
- def map_config_to_object(content_source: str):
40
- if content_source == DbEntry.EntrySource.GITHUB:
41
- return GithubConfig
42
- if content_source == DbEntry.EntrySource.NOTION:
43
- return NotionConfig
44
- if content_source == DbEntry.EntrySource.COMPUTER:
45
- return "Computer"
46
-
47
-
48
- async def map_config_to_db(config: FullConfig, user: KhojUser):
49
- if config.content_type:
50
- if config.content_type.org:
51
- await LocalOrgConfig.objects.filter(user=user).adelete()
52
- await LocalOrgConfig.objects.acreate(
53
- input_files=config.content_type.org.input_files,
54
- input_filter=config.content_type.org.input_filter,
55
- index_heading_entries=config.content_type.org.index_heading_entries,
56
- user=user,
57
- )
58
- if config.content_type.markdown:
59
- await LocalMarkdownConfig.objects.filter(user=user).adelete()
60
- await LocalMarkdownConfig.objects.acreate(
61
- input_files=config.content_type.markdown.input_files,
62
- input_filter=config.content_type.markdown.input_filter,
63
- index_heading_entries=config.content_type.markdown.index_heading_entries,
64
- user=user,
65
- )
66
- if config.content_type.pdf:
67
- await LocalPdfConfig.objects.filter(user=user).adelete()
68
- await LocalPdfConfig.objects.acreate(
69
- input_files=config.content_type.pdf.input_files,
70
- input_filter=config.content_type.pdf.input_filter,
71
- index_heading_entries=config.content_type.pdf.index_heading_entries,
72
- user=user,
73
- )
74
- if config.content_type.plaintext:
75
- await LocalPlaintextConfig.objects.filter(user=user).adelete()
76
- await LocalPlaintextConfig.objects.acreate(
77
- input_files=config.content_type.plaintext.input_files,
78
- input_filter=config.content_type.plaintext.input_filter,
79
- index_heading_entries=config.content_type.plaintext.index_heading_entries,
80
- user=user,
81
- )
82
- if config.content_type.github:
83
- await adapters.set_user_github_config(
84
- user=user,
85
- pat_token=config.content_type.github.pat_token,
86
- repos=config.content_type.github.repos,
87
- )
88
- if config.content_type.notion:
89
- await adapters.set_notion_config(
90
- user=user,
91
- token=config.content_type.notion.token,
92
- )
93
-
94
-
95
- def _initialize_config():
96
- if state.config is None:
97
- state.config = FullConfig()
98
- state.config.search_type = SearchConfig.model_validate(constants.default_config["search-type"])
99
-
100
-
101
- @api_config.post("/data/content-source/github", status_code=200)
102
- @requires(["authenticated"])
103
- async def set_content_config_github_data(
104
- request: Request,
105
- updated_config: Union[GithubContentConfig, None],
106
- client: Optional[str] = None,
107
- ):
108
- _initialize_config()
109
-
110
- user = request.user.object
111
-
112
- try:
113
- await adapters.set_user_github_config(
114
- user=user,
115
- pat_token=updated_config.pat_token,
116
- repos=updated_config.repos,
117
- )
118
- except Exception as e:
119
- logger.error(e, exc_info=True)
120
- raise HTTPException(status_code=500, detail="Failed to set Github config")
121
-
122
- update_telemetry_state(
123
- request=request,
124
- telemetry_type="api",
125
- api="set_content_config",
126
- client=client,
127
- metadata={"content_type": "github"},
128
- )
129
-
130
- return {"status": "ok"}
131
-
132
-
133
- @api_config.post("/data/content-source/notion", status_code=200)
134
- @requires(["authenticated"])
135
- async def set_content_config_notion_data(
136
- request: Request,
137
- updated_config: Union[NotionContentConfig, None],
138
- client: Optional[str] = None,
139
- ):
140
- _initialize_config()
141
-
142
- user = request.user.object
143
-
144
- try:
145
- await adapters.set_notion_config(
146
- user=user,
147
- token=updated_config.token,
148
- )
149
- except Exception as e:
150
- logger.error(e, exc_info=True)
151
- raise HTTPException(status_code=500, detail="Failed to set Github config")
152
-
153
- update_telemetry_state(
154
- request=request,
155
- telemetry_type="api",
156
- api="set_content_config",
157
- client=client,
158
- metadata={"content_type": "notion"},
159
- )
160
-
161
- return {"status": "ok"}
162
-
163
-
164
- @api_config.delete("/data/content-source/{content_source}", status_code=200)
165
- @requires(["authenticated"])
166
- async def remove_content_source_data(
167
- request: Request,
168
- content_source: str,
169
- client: Optional[str] = None,
170
- ):
171
- user = request.user.object
172
-
173
- update_telemetry_state(
174
- request=request,
175
- telemetry_type="api",
176
- api="delete_content_config",
177
- client=client,
178
- metadata={"content_source": content_source},
179
- )
180
-
181
- content_object = map_config_to_object(content_source)
182
- if content_object is None:
183
- raise ValueError(f"Invalid content source: {content_source}")
184
- elif content_object != "Computer":
185
- await content_object.objects.filter(user=user).adelete()
186
- await sync_to_async(EntryAdapters.delete_all_entries)(user, file_source=content_source)
187
-
188
- enabled_content = await sync_to_async(EntryAdapters.get_unique_file_types)(user)
189
- return {"status": "ok"}
190
-
191
-
192
- @api_config.delete("/data/file", status_code=200)
193
- @requires(["authenticated"])
194
- async def remove_file_data(
195
- request: Request,
196
- filename: str,
197
- client: Optional[str] = None,
198
- ):
199
- user = request.user.object
200
-
201
- update_telemetry_state(
202
- request=request,
203
- telemetry_type="api",
204
- api="delete_file",
205
- client=client,
206
- )
207
-
208
- await EntryAdapters.adelete_entry_by_file(user, filename)
209
-
210
- return {"status": "ok"}
211
-
212
-
213
- @api_config.get("/data/{content_source}", response_model=List[str])
214
- @requires(["authenticated"])
215
- async def get_all_filenames(
216
- request: Request,
217
- content_source: str,
218
- client: Optional[str] = None,
219
- ):
220
- user = request.user.object
221
-
222
- update_telemetry_state(
223
- request=request,
224
- telemetry_type="api",
225
- api="get_all_filenames",
226
- client=client,
227
- )
228
-
229
- return await sync_to_async(list)(EntryAdapters.get_all_filenames_by_source(user, content_source)) # type: ignore[call-arg]
230
-
231
-
232
- @api_config.get("/data/conversation/model/options", response_model=Dict[str, Union[str, int]])
233
- def get_chat_model_options(
234
- request: Request,
235
- client: Optional[str] = None,
236
- ):
237
- conversation_options = ConversationAdapters.get_conversation_processor_options().all()
238
-
239
- all_conversation_options = list()
240
- for conversation_option in conversation_options:
241
- all_conversation_options.append({"chat_model": conversation_option.chat_model, "id": conversation_option.id})
242
-
243
- return Response(content=json.dumps(all_conversation_options), media_type="application/json", status_code=200)
244
-
245
-
246
- @api_config.get("/data/conversation/model")
247
- @requires(["authenticated"])
248
- def get_user_chat_model(
249
- request: Request,
250
- client: Optional[str] = None,
251
- ):
252
- user = request.user.object
253
-
254
- chat_model = ConversationAdapters.get_conversation_config(user)
255
-
256
- if chat_model is None:
257
- chat_model = ConversationAdapters.get_default_conversation_config()
258
-
259
- return Response(status_code=200, content=json.dumps({"id": chat_model.id, "chat_model": chat_model.chat_model}))
260
-
261
-
262
- @api_config.post("/data/conversation/model", status_code=200)
263
- @requires(["authenticated", "premium"])
264
- async def update_chat_model(
265
- request: Request,
266
- id: str,
267
- client: Optional[str] = None,
268
- ):
269
- user = request.user.object
270
-
271
- new_config = await ConversationAdapters.aset_user_conversation_processor(user, int(id))
272
-
273
- update_telemetry_state(
274
- request=request,
275
- telemetry_type="api",
276
- api="set_conversation_chat_model",
277
- client=client,
278
- metadata={"processor_conversation_type": "conversation"},
279
- )
280
-
281
- if new_config is None:
282
- return {"status": "error", "message": "Model not found"}
283
-
284
- return {"status": "ok"}
285
-
286
-
287
- @api_config.post("/data/voice/model", status_code=200)
288
- @requires(["authenticated", "premium"])
289
- async def update_voice_model(
290
- request: Request,
291
- id: str,
292
- client: Optional[str] = None,
293
- ):
294
- user = request.user.object
295
-
296
- new_config = await ConversationAdapters.aset_user_voice_model(user, id)
297
-
298
- update_telemetry_state(
299
- request=request,
300
- telemetry_type="api",
301
- api="set_voice_model",
302
- client=client,
303
- )
304
-
305
- if new_config is None:
306
- return Response(status_code=404, content=json.dumps({"status": "error", "message": "Model not found"}))
307
-
308
- return Response(status_code=202, content=json.dumps({"status": "ok"}))
309
-
310
-
311
- @api_config.post("/data/search/model", status_code=200)
312
- @requires(["authenticated"])
313
- async def update_search_model(
314
- request: Request,
315
- id: str,
316
- client: Optional[str] = None,
317
- ):
318
- user = request.user.object
319
-
320
- prev_config = await adapters.aget_user_search_model(user)
321
- new_config = await adapters.aset_user_search_model(user, int(id))
322
-
323
- if prev_config and int(id) != prev_config.id and new_config:
324
- await EntryAdapters.adelete_all_entries(user)
325
-
326
- if not prev_config:
327
- # If the use was just using the default config, delete all the entries and set the new config.
328
- await EntryAdapters.adelete_all_entries(user)
329
-
330
- if new_config is None:
331
- return {"status": "error", "message": "Model not found"}
332
- else:
333
- update_telemetry_state(
334
- request=request,
335
- telemetry_type="api",
336
- api="set_search_model",
337
- client=client,
338
- metadata={"search_model": new_config.setting.name},
339
- )
340
-
341
- return {"status": "ok"}
342
-
343
-
344
- @api_config.post("/data/paint/model", status_code=200)
345
- @requires(["authenticated"])
346
- async def update_paint_model(
347
- request: Request,
348
- id: str,
349
- client: Optional[str] = None,
350
- ):
351
- user = request.user.object
352
- subscribed = has_required_scope(request, ["premium"])
353
-
354
- if not subscribed:
355
- raise HTTPException(status_code=403, detail="User is not subscribed to premium")
356
-
357
- new_config = await ConversationAdapters.aset_user_text_to_image_model(user, int(id))
358
-
359
- update_telemetry_state(
360
- request=request,
361
- telemetry_type="api",
362
- api="set_paint_model",
363
- client=client,
364
- metadata={"paint_model": new_config.setting.model_name},
365
- )
366
-
367
- if new_config is None:
368
- return {"status": "error", "message": "Model not found"}
369
-
370
- return {"status": "ok"}
371
-
372
-
373
- @api_config.get("/index/size", response_model=Dict[str, int])
374
- @requires(["authenticated"])
375
- async def get_indexed_data_size(request: Request, common: CommonQueryParams):
376
- user = request.user.object
377
- indexed_data_size_in_mb = await sync_to_async(EntryAdapters.get_size_of_indexed_data_in_mb)(user)
378
- return Response(
379
- content=json.dumps({"indexed_data_size_in_mb": math.ceil(indexed_data_size_in_mb)}),
380
- media_type="application/json",
381
- status_code=200,
382
- )
383
-
384
-
385
- @api_config.post("/user/name", status_code=200)
386
- @requires(["authenticated"])
387
- def set_user_name(
388
- request: Request,
389
- name: str,
390
- client: Optional[str] = None,
391
- ):
392
- user = request.user.object
393
-
394
- split_name = name.split(" ")
395
-
396
- if len(split_name) > 2:
397
- raise HTTPException(status_code=400, detail="Name must be in the format: Firstname Lastname")
398
-
399
- if len(split_name) == 1:
400
- first_name = split_name[0]
401
- last_name = ""
402
- else:
403
- first_name, last_name = split_name[0], split_name[-1]
404
-
405
- adapters.set_user_name(user, first_name, last_name)
406
-
407
- update_telemetry_state(
408
- request=request,
409
- telemetry_type="api",
410
- api="set_user_name",
411
- client=client,
412
- )
413
-
414
- return {"status": "ok"}
415
-
416
-
417
- @api_config.get("/types", response_model=List[str])
418
- @requires(["authenticated"])
419
- def get_config_types(
420
- request: Request,
421
- ):
422
- user = request.user.object
423
- enabled_file_types = EntryAdapters.get_unique_file_types(user)
424
- configured_content_types = list(enabled_file_types)
425
-
426
- if state.config and state.config.content_type:
427
- for ctype in state.config.content_type.model_dump(exclude_none=True):
428
- configured_content_types.append(ctype)
429
-
430
- return [
431
- search_type.value
432
- for search_type in SearchType
433
- if (search_type.value in configured_content_types) or search_type == SearchType.All
434
- ]