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
@@ -0,0 +1,26 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" className="fill-zinc-950 dark:fill-zinc-300" xmlns="http://www.w3.org/2000/svg">
2
+ <g clipPath="url(#clip0_45_75)">
3
+ <!-- Fire -->
4
+ <path d="M57.9394 93.0404L67.5396 49.1063C68.7987 49.5268 71.7365 51.9442 74.7267 51.9442C78.5039 51.9442 79.2383 47.4246 86.1631 45.7955C91.6715 44.4817 96.3404 45.4276 99.0684 47.6349C99.0684 47.6349 99.6979 53.6259 101.167 55.4127C102.531 57.0418 104.629 56.4637 104.629 56.4637C107.672 70.8106 114.072 100.661 115.279 105.233C116.8 110.961 110.924 114.114 108.669 119.369C106.413 124.625 94.242 126.884 87.0549 127.62C79.8679 128.356 59.723 119.632 57.9394 117.215C56.1557 114.797 55.3688 109.857 55.1065 105.18C54.8442 101.449 56.8902 95.5104 57.9394 93.0404Z" fill="#FAE80B" />
5
+ <path d="M57.9394 92.9879L62.2936 74.8046C63.5526 75.2251 66.9626 73.4383 71.4742 69.0764C74.1497 66.4488 79.8678 58.8812 86.0582 55.3601C90.5698 52.785 94.924 54.204 97.5995 56.4112C97.5995 56.4112 100.013 57.6199 102.846 57.6199C104.944 57.6199 104.629 56.4112 104.629 56.4112C107.672 70.7581 114.072 100.608 115.279 105.18C116.8 110.908 110.924 114.062 108.669 119.317C106.413 124.572 94.242 126.832 87.0549 127.568C79.8679 128.303 59.723 119.58 57.9394 117.162C56.1557 114.745 55.3688 109.805 55.1065 105.128C54.8442 101.449 56.8902 95.5104 57.9394 92.9879Z" fill="#FFCC09" />
6
+ <path d="M69.3233 123.731C58.9886 121.104 55.8934 109.069 55.6311 103.393C58.7787 106.599 67.12 112.8 75.1464 111.959C85.2188 110.908 92.7207 106.862 100.852 100.503C108.983 94.1966 114.544 97.1921 114.544 106.809C114.544 116.426 107.619 118.108 105.521 122.47C103.423 126.884 82.281 127.042 69.3233 123.731Z" fill="#FBA719" />
7
+
8
+ <!-- Lamp -->
9
+ <path d="M46.6374 143.679C43.5946 143.679 41.2864 142.838 39.6601 141.104C36.7223 138.004 37.5092 133.379 37.5617 133.169C37.719 132.275 52.3031 43.8816 53.667 35.2104C54.9261 27.1698 64.0542 25.383 68.7232 25.5932L68.6183 28.7464C68.5658 28.7464 65.733 28.6413 62.8476 29.5347C59.2803 30.6383 57.2344 32.6878 56.7622 35.6834C55.4507 44.3546 40.8142 132.801 40.6568 133.694C40.6568 133.747 40.1322 137.005 41.9684 138.95C43.2799 140.316 45.4832 140.789 48.6308 140.368L48.9981 143.469C48.2112 143.627 47.4243 143.679 46.6374 143.679Z" />
10
+ <path d="M106.023 33.371H102.928C102.98 33.2133 102.98 33.0031 102.98 32.8455V15.2403C102.98 13.506 101.564 12.0871 99.8324 12.0871H89.4977C90.8616 10.8784 91.7535 9.09161 91.7535 7.09461C91.7535 3.41592 88.7632 0.42041 85.091 0.42041C81.4188 0.42041 78.4285 3.41592 78.4285 7.09461C78.4285 9.09161 79.2679 10.8784 80.6843 12.0871H70.8217C69.0905 12.0871 67.6741 13.506 67.6741 15.2403V32.8455C67.6741 33.0557 67.6741 33.2133 67.7265 33.371H64.0543C61.5887 33.371 59.5427 35.4205 59.5427 37.8905C59.5427 40.4131 61.5887 42.4101 64.0543 42.4101H106.075C108.541 42.4101 110.587 40.3605 110.587 37.8905C110.534 35.368 108.541 33.371 106.023 33.371ZM85.0385 3.52103C86.9795 3.52103 88.5534 5.0976 88.5534 7.04205C88.5534 8.98651 86.9795 10.5631 85.0385 10.5631C83.0975 10.5631 81.5237 8.98651 81.5237 7.04205C81.5237 5.0976 83.0975 3.52103 85.0385 3.52103Z" />
11
+ <path d="M123.177 143.679C122.443 143.679 121.656 143.627 120.816 143.522L121.184 140.421C124.331 140.841 126.535 140.316 127.846 139.002C129.682 137.058 129.158 133.799 129.158 133.799C129 132.906 114.364 44.4596 113.052 35.7884C112.58 32.7929 110.534 30.7433 106.967 29.6397C104.082 28.7463 101.249 28.8514 101.196 28.8514L101.091 25.6983C105.76 25.4881 114.941 27.2749 116.147 35.3154C117.459 43.9866 132.095 132.38 132.253 133.274C132.305 133.431 133.092 138.056 130.154 141.157C128.528 142.786 126.22 143.679 123.177 143.679Z" />
12
+ <path d="M122.443 151.142L122.39 129.805C122.39 124.76 109.642 120.031 109.642 120.031H109.433C105.026 124.34 97.5765 127.44 85.2483 127.44C72.9201 127.44 65.5231 124.34 61.064 120.031H60.8541C60.8541 120.031 48.1063 124.76 48.1063 129.805C48.1063 134.85 48.1063 151.142 48.1063 151.142C48.1063 151.142 42.1782 154.978 42.1782 159.445C42.1782 163.912 42.1782 167.17 42.1782 167.17C42.1782 167.17 47.2144 178.154 85.2483 178.154H85.3007C123.335 178.154 128.371 167.17 128.371 167.17C128.371 167.17 128.371 163.912 128.371 159.445C128.371 154.978 122.443 151.142 122.443 151.142Z" />
13
+ <path d="M117.931 87.658C116.725 85.2406 113.42 80.5108 112.056 78.5664L103.924 41.1488L101.091 41.7795L112.738 95.2256L112.79 95.3833C112.79 95.4358 113.262 96.8547 113.63 99.062C113.052 99.5875 112.37 100.06 111.584 100.533C108.331 102.478 96.7897 105.894 85.3009 108.994C73.8645 105.894 62.3756 102.478 59.1231 100.533C58.2837 100.008 57.5493 99.4824 56.9197 98.9043C57.287 96.7496 57.7066 95.3833 57.7591 95.3307V95.2782L69.4053 41.5167L66.5725 40.886L58.3362 79.0394C56.8148 81.194 53.877 85.4508 52.7754 87.7106C51.8311 89.6025 50.7819 94.5424 54.0344 98.8518C53.2475 103.739 52.9852 111.78 57.7591 118.401C62.7953 125.391 72.0284 128.912 85.2484 128.912C98.4685 128.912 107.702 125.391 112.738 118.401C117.459 111.832 117.249 103.949 116.515 99.062C120.03 94.6475 118.928 89.6025 117.931 87.658ZM116.095 88.604C116.725 89.9178 117.459 92.9658 115.99 96.0139C115.78 95.2256 115.623 94.7526 115.571 94.5424L113.262 83.9793C114.364 85.661 115.518 87.4478 116.095 88.604ZM54.664 88.604C55.1886 87.5529 56.1328 86.0289 57.182 84.4523L54.9787 94.4899C54.9262 94.6475 54.7689 95.068 54.6115 95.6986C53.4049 92.7556 54.0869 89.8652 54.664 88.604ZM56.6574 101.374C57.0771 101.69 57.6017 102.005 58.0739 102.32C61.1166 104.16 70.9792 107.155 81.3139 110.045C70.5595 112.936 60.8543 115.301 59.4378 115.669C56.5525 110.939 56.2902 105.473 56.6574 101.374ZM85.3009 125.969C73.6546 125.969 65.4184 123.131 60.8018 117.508C64.1068 116.72 74.5465 114.092 85.3533 111.149C95.9504 114.039 106.338 116.615 109.8 117.508C105.183 123.131 96.9471 125.969 85.3009 125.969ZM111.111 115.669C109.17 115.196 99.7275 112.831 89.3403 110.045C99.7275 107.155 109.59 104.107 112.685 102.268C113.157 102.005 113.525 101.742 113.944 101.427C114.311 105.526 113.997 110.991 111.111 115.669Z" />
14
+ <path d="M39.188 44.7224C38.8733 44.7224 38.611 44.6173 38.3487 44.4597L24.2893 34.5797C23.6073 34.1068 23.4499 33.2134 23.922 32.5302C24.3942 31.847 25.286 31.6893 25.968 32.1623L40.0274 42.0422C40.7094 42.5152 40.8668 43.4086 40.3946 44.0918C40.0799 44.5122 39.6602 44.7224 39.188 44.7224Z" />
15
+ <path d="M18.8334 80.6685L1.67885 80.6159C0.891941 80.6159 0.209961 79.9853 0.209961 79.1445C0.209961 78.3036 0.83948 77.673 1.67885 77.673L18.8334 77.7255C19.6203 77.7255 20.3023 78.3562 20.3023 79.197C20.3023 80.0379 19.6203 80.6685 18.8334 80.6685Z" />
16
+ <path d="M13.2726 128.754C12.8004 128.754 12.3283 128.544 12.066 128.071C11.6463 127.388 11.8562 126.495 12.4857 126.074L26.9123 116.825C27.5943 116.404 28.4861 116.562 28.9058 117.245C29.3255 117.928 29.1157 118.822 28.4861 119.242L14.0595 128.492C13.8497 128.649 13.5874 128.754 13.2726 128.754Z" />
17
+ <path d="M130.889 43.6188C130.417 43.6188 129.997 43.4086 129.682 42.9881C129.21 42.305 129.368 41.4116 130.05 40.9386L144.109 31.0587C144.738 30.5857 145.683 30.7433 146.155 31.4265C146.627 32.1097 146.47 33.0031 145.788 33.4761L131.728 43.356C131.466 43.5137 131.204 43.6188 130.889 43.6188Z" />
18
+ <path d="M151.244 79.5649C150.457 79.5649 149.775 78.9343 149.775 78.0934C149.775 77.3051 150.404 76.6219 151.244 76.6219L168.398 76.5694C169.185 76.5694 169.867 77.2 169.867 78.0409C169.867 78.8292 169.238 79.5123 168.398 79.5123L151.244 79.5649Z" />
19
+ <path d="M156.804 127.598C156.542 127.598 156.28 127.546 156.017 127.388L141.591 118.139C140.909 117.718 140.699 116.825 141.171 116.142C141.591 115.458 142.483 115.248 143.165 115.721L157.591 124.97C158.273 125.391 158.483 126.284 158.011 126.967C157.749 127.388 157.277 127.598 156.804 127.598Z" />
20
+ </g>
21
+ <defs>
22
+ <clipPath id="clip0_45_75">
23
+ <rect width="200" height="200" fill="currentColor" />
24
+ </clipPath>
25
+ </defs>
26
+ </svg>
@@ -44,7 +44,7 @@ Hi, I am Khoj, your open, personal AI 👋🏽. I can:
44
44
  - 📚 Understand files you drag & drop here
45
45
  - 👩🏾‍🚀 Be tuned to your conversation needs via [agents](./agents)
46
46
 
47
- Get the Khoj [Desktop](https://khoj.dev/downloads), [Obsidian](https://docs.khoj.dev/clients/obsidian#setup), [Emacs](https://docs.khoj.dev/clients/emacs#setup) apps to search, chat with your 🖥️ computer docs. You can manage all the files you've shared with me at any time by going to [your settings](/config/content-source/computer/).
47
+ Get the Khoj [Desktop](https://khoj.dev/downloads), [Obsidian](https://docs.khoj.dev/clients/obsidian#setup), [Emacs](https://docs.khoj.dev/clients/emacs#setup) apps to search, chat with your 🖥️ computer docs. You can manage all the files you've shared with me at any time by going to [your settings](/settings/content/computer/).
48
48
 
49
49
  To get started, just start typing below. You can also type / to see a list of commands.
50
50
  `.trim()
@@ -1058,8 +1058,8 @@ To get started, just start typing below. You can also type / to see a list of co
1058
1058
  // Wait for all files to be read before making the fetch request
1059
1059
  Promise.all(fileReadPromises)
1060
1060
  .then(() => {
1061
- return fetch("/api/v1/index/update?force=false&client=web", {
1062
- method: "POST",
1061
+ return fetch("/api/content?client=web", {
1062
+ method: "PATCH",
1063
1063
  body: formData,
1064
1064
  });
1065
1065
  })
@@ -1223,7 +1223,7 @@ To get started, just start typing below. You can also type / to see a list of co
1223
1223
  - 📚 Understand files you drag & drop here
1224
1224
  - 👩🏾‍🚀 Be tuned to your conversation needs via [agents](./agents)
1225
1225
 
1226
- Get the Khoj [Desktop](https://khoj.dev/downloads), [Obsidian](https://docs.khoj.dev/clients/obsidian#setup), or [Emacs](https://docs.khoj.dev/clients/emacs#setup) app to keep your files in sync. You can manage all the files you've shared with me at any time by going to [your settings](/config/content-source/computer/).
1226
+ Get the Khoj [Desktop](https://khoj.dev/downloads), [Obsidian](https://docs.khoj.dev/clients/obsidian#setup), or [Emacs](https://docs.khoj.dev/clients/emacs#setup) app to keep your files in sync. You can manage all the files you've shared with me at any time by going to [your settings](/settings/content/computer/).
1227
1227
 
1228
1228
  To get started, just start typing below. You can also type / to see a list of commands.
1229
1229
 
@@ -1844,7 +1844,7 @@ To get started, just start typing below. You can also type / to see a list of co
1844
1844
  }
1845
1845
  var allFiles;
1846
1846
  function renderAllFiles() {
1847
- fetch('/api/config/data/computer')
1847
+ fetch('/api/content/computer')
1848
1848
  .then(response => response.json())
1849
1849
  .then(data => {
1850
1850
  var indexedFiles = document.getElementsByClassName("indexed-files")[0];
@@ -32,7 +32,7 @@
32
32
  </style>
33
33
  <script>
34
34
  function removeFile(path) {
35
- fetch('/api/config/data/file?filename=' + path, {
35
+ fetch('/api/content/file?filename=' + path, {
36
36
  method: 'DELETE',
37
37
  headers: {
38
38
  'Content-Type': 'application/json',
@@ -48,7 +48,7 @@
48
48
 
49
49
  // Get all currently indexed files
50
50
  function getAllComputerFilenames() {
51
- fetch('/api/config/data/computer')
51
+ fetch('/api/content/computer')
52
52
  .then(response => response.json())
53
53
  .then(data => {
54
54
  var indexedFiles = document.getElementsByClassName("indexed-files")[0];
@@ -122,7 +122,7 @@
122
122
  deleteAllComputerFilesButton.textContent = "🗑️ Deleting...";
123
123
  deleteAllComputerFilesButton.disabled = true;
124
124
 
125
- fetch('/api/config/data/content-source/computer', {
125
+ fetch('/api/content/computer', {
126
126
  method: 'DELETE',
127
127
  headers: {
128
128
  'Content-Type': 'application/json',
@@ -165,7 +165,7 @@
165
165
 
166
166
  // Save Github config on server
167
167
  const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
168
- fetch('/api/config/data/content-source/github', {
168
+ fetch('/api/content/github', {
169
169
  method: 'POST',
170
170
  headers: {
171
171
  'Content-Type': 'application/json',
@@ -45,7 +45,7 @@
45
45
 
46
46
  // Save Notion config on server
47
47
  const csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken'))?.split('=')[1];
48
- fetch('/api/config/data/content-source/notion', {
48
+ fetch('/api/content/notion', {
49
49
  method: 'POST',
50
50
  headers: {
51
51
  'Content-Type': 'application/json',
@@ -34,7 +34,7 @@ Hi, I am Khoj, your open, personal AI 👋🏽. I can:
34
34
  - 📚 Understand files you drag & drop here
35
35
  - 👩🏾‍🚀 Be tuned to your conversation needs via [agents](./agents)
36
36
 
37
- Get the Khoj [Desktop](https://khoj.dev/downloads), [Obsidian](https://docs.khoj.dev/clients/obsidian#setup), [Emacs](https://docs.khoj.dev/clients/emacs#setup) apps to search, chat with your 🖥️ computer docs. You can manage all the files you've shared with me at any time by going to [your settings](/config/content-source/computer/).
37
+ Get the Khoj [Desktop](https://khoj.dev/downloads), [Obsidian](https://docs.khoj.dev/clients/obsidian#setup), [Emacs](https://docs.khoj.dev/clients/emacs#setup) apps to search, chat with your 🖥️ computer docs. You can manage all the files you've shared with me at any time by going to [your settings](/settings/content/computer/).
38
38
 
39
39
  To get started, just start typing below. You can also type / to see a list of commands.
40
40
  `.trim()
@@ -209,12 +209,12 @@
209
209
 
210
210
  function populate_type_dropdown() {
211
211
  // Populate type dropdown field with enabled content types only
212
- fetch("/api/config/types")
212
+ fetch("/api/content/types")
213
213
  .then(response => response.json())
214
214
  .then(enabled_types => {
215
215
  // Show warning if no content types are enabled, or just one ("all")
216
216
  if (enabled_types[0] === "all" && enabled_types.length === 1) {
217
- document.getElementById("results").innerHTML = "<div id='results-error'>To use Khoj search, setup your content plugins on the Khoj <a class='inline-chat-link' href='/config'>settings page</a>.</div>";
217
+ document.getElementById("results").innerHTML = "<div id='results-error'>To use Khoj search, setup your content plugins on the Khoj <a class='inline-chat-link' href='/settings'>settings page</a>.</div>";
218
218
  document.getElementById("query").setAttribute("disabled", "disabled");
219
219
  document.getElementById("query").setAttribute("placeholder", "Configure Khoj to enable search");
220
220
  return [];
@@ -34,7 +34,7 @@
34
34
  <h3 id="card-title-computer" class="card-title">
35
35
  <span>Files</span>
36
36
  <img id="configured-icon-computer"
37
- style="display: {% if not current_model_state.computer %}none{% endif %}"
37
+ style="display: {% if not enabled_content_source.computer %}none{% endif %}"
38
38
  class="configured-icon"
39
39
  src="/static/assets/icons/confirm-icon.svg"
40
40
  alt="Configured">
@@ -44,8 +44,8 @@
44
44
  <p class="card-description">Manage files from your computer</p>
45
45
  </div>
46
46
  <div class="card-action-row">
47
- <a class="card-button" href="/config/content-source/computer">
48
- {% if current_model_state.computer %}
47
+ <a class="card-button" href="/settings/content/computer">
48
+ {% if enabled_content_source.computer %}
49
49
  Update
50
50
  {% else %}
51
51
  Setup
@@ -53,7 +53,7 @@
53
53
  <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
54
54
  </a>
55
55
  <div id="clear-computer" class="card-action-row"
56
- style="display: {% if not current_model_state.computer %}none{% endif %}">
56
+ style="display: {% if not enabled_content_source.computer %}none{% endif %}">
57
57
  <button class="card-button" onclick="clearContentType('computer')">
58
58
  Disable
59
59
  </button>
@@ -69,15 +69,15 @@
69
69
  class="configured-icon"
70
70
  src="/static/assets/icons/confirm-icon.svg"
71
71
  alt="Configured"
72
- style="display: {% if not current_model_state.github %}none{% endif %}">
72
+ style="display: {% if not enabled_content_source.github %}none{% endif %}">
73
73
  </h3>
74
74
  </div>
75
75
  <div class="card-description-row">
76
76
  <p class="card-description">Set repositories to index</p>
77
77
  </div>
78
78
  <div class="card-action-row">
79
- <a class="card-button" href="/config/content-source/github">
80
- {% if current_model_state.github %}
79
+ <a class="card-button" href="/settings/content/github">
80
+ {% if enabled_content_source.github %}
81
81
  Update
82
82
  {% else %}
83
83
  Setup
@@ -86,7 +86,7 @@
86
86
  </a>
87
87
  <div id="clear-github"
88
88
  class="card-action-row"
89
- style="display: {% if not current_model_state.github %}none{% endif %}">
89
+ style="display: {% if not enabled_content_source.github %}none{% endif %}">
90
90
  <button class="card-button" onclick="clearContentType('github')">
91
91
  Disable
92
92
  </button>
@@ -102,15 +102,15 @@
102
102
  class="configured-icon"
103
103
  src="/static/assets/icons/confirm-icon.svg"
104
104
  alt="Configured"
105
- style="display: {% if not current_model_state.notion %}none{% endif %}">
105
+ style="display: {% if not enabled_content_source.notion %}none{% endif %}">
106
106
  </h3>
107
107
  </div>
108
108
  <div class="card-description-row">
109
109
  <p class="card-description">Sync your Notion pages</p>
110
110
  </div>
111
111
  <div class="card-action-row">
112
- {% if current_model_state.notion %}
113
- <a class="card-button" href="/config/content-source/notion">
112
+ {% if enabled_content_source.notion %}
113
+ <a class="card-button" href="/settings/content/notion">
114
114
  Update
115
115
  <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
116
116
  </a>
@@ -120,7 +120,7 @@
120
120
  <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
121
121
  </a>
122
122
  {% else %}
123
- <a class="card-button" href="/config/content-source/notion">
123
+ <a class="card-button" href="/settings/content/notion">
124
124
  Setup
125
125
  <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"></path></svg>
126
126
  </a>
@@ -128,7 +128,7 @@
128
128
 
129
129
  <div id="clear-notion"
130
130
  class="card-action-row"
131
- style="display: {% if not current_model_state.notion %}none{% endif %}">
131
+ style="display: {% if not enabled_content_source.notion %}none{% endif %}">
132
132
  <button class="card-button" onclick="clearContentType('notion')">
133
133
  Disable
134
134
  </button>
@@ -181,8 +181,8 @@
181
181
  </div>
182
182
  <div class="card-description-row">
183
183
  <select id="chat-models">
184
- {% for option in conversation_options %}
185
- <option value="{{ option.id }}" {% if option.id == selected_conversation_config %}selected{% endif %}>{{ option.chat_model }}</option>
184
+ {% for option in chat_model_options %}
185
+ <option value="{{ option.id }}" {% if option.id == selected_chat_model_config %}selected{% endif %}>{{ option.name }}</option>
186
186
  {% endfor %}
187
187
  </select>
188
188
  </div>
@@ -208,7 +208,7 @@
208
208
  <div class="card-description-row">
209
209
  <select id="paint-models">
210
210
  {% for option in paint_model_options %}
211
- <option value="{{ option.id }}" {% if option.id == selected_paint_model_config %}selected{% endif %}>{{ option.model_name }}</option>
211
+ <option value="{{ option.id }}" {% if option.id == selected_paint_model_config %}selected{% endif %}>{{ option.name }}</option>
212
212
  {% endfor %}
213
213
  </select>
214
214
  </div>
@@ -235,7 +235,7 @@
235
235
  <div class="card-description-row">
236
236
  <select id="voice-models">
237
237
  {% for option in voice_model_options %}
238
- <option value="{{ option.id }}" {% if option.id == selected_voice_config %}selected{% endif %}>{{ option.name }}</option>
238
+ <option value="{{ option.id }}" {% if option.id == selected_voice_model_config %}selected{% endif %}>{{ option.name }}</option>
239
239
  {% endfor %}
240
240
  </select>
241
241
  </div>
@@ -394,8 +394,8 @@
394
394
 
395
395
  function saveProfileGivenName() {
396
396
  const givenName = document.getElementById("profile_given_name").value;
397
- fetch('/api/config/user/name?name=' + givenName, {
398
- method: 'POST',
397
+ fetch('/api/user/name?name=' + givenName, {
398
+ method: 'PATCH',
399
399
  headers: {
400
400
  'Content-Type': 'application/json',
401
401
  }
@@ -421,7 +421,7 @@
421
421
  saveVoiceModelButton.disabled = true;
422
422
  saveVoiceModelButton.textContent = "Saving...";
423
423
 
424
- fetch('/api/config/data/voice/model?id=' + voiceModel, {
424
+ fetch('/api/model/voice?id=' + voiceModel, {
425
425
  method: 'POST',
426
426
  headers: {
427
427
  'Content-Type': 'application/json',
@@ -455,7 +455,7 @@
455
455
  saveModelButton.innerHTML = "";
456
456
  saveModelButton.textContent = "Saving...";
457
457
 
458
- fetch('/api/config/data/conversation/model?id=' + chatModel, {
458
+ fetch('/api/model/chat?id=' + chatModel, {
459
459
  method: 'POST',
460
460
  headers: {
461
461
  'Content-Type': 'application/json',
@@ -494,7 +494,7 @@
494
494
  saveSearchModelButton.disabled = true;
495
495
  saveSearchModelButton.textContent = "Saving...";
496
496
 
497
- fetch('/api/config/data/search/model?id=' + searchModel, {
497
+ fetch('/api/model/search?id=' + searchModel, {
498
498
  method: 'POST',
499
499
  headers: {
500
500
  'Content-Type': 'application/json',
@@ -526,7 +526,7 @@
526
526
  saveModelButton.disabled = true;
527
527
  saveModelButton.innerHTML = "Saving...";
528
528
 
529
- fetch('/api/config/data/paint/model?id=' + paintModel, {
529
+ fetch('/api/model/paint?id=' + paintModel, {
530
530
  method: 'POST',
531
531
  headers: {
532
532
  'Content-Type': 'application/json',
@@ -553,7 +553,7 @@
553
553
  };
554
554
 
555
555
  function clearContentType(content_source) {
556
- fetch('/api/config/data/content-source/' + content_source, {
556
+ fetch('/api/content/' + content_source, {
557
557
  method: 'DELETE',
558
558
  headers: {
559
559
  'Content-Type': 'application/json',
@@ -676,7 +676,7 @@
676
676
 
677
677
  content_sources = ["computer", "github", "notion"];
678
678
  content_sources.forEach(content_source => {
679
- fetch(`/api/config/data/${content_source}`, {
679
+ fetch(`/api/content/${content_source}`, {
680
680
  method: 'GET',
681
681
  headers: {
682
682
  'Content-Type': 'application/json',
@@ -807,7 +807,7 @@
807
807
 
808
808
  function getIndexedDataSize() {
809
809
  document.getElementById("indexed-data-size").textContent = "Calculating...";
810
- fetch('/api/config/index/size')
810
+ fetch('/api/content/size')
811
811
  .then(response => response.json())
812
812
  .then(data => {
813
813
  document.getElementById("indexed-data-size").textContent = data.indexed_data_size_in_mb + " MB used";
@@ -815,7 +815,7 @@
815
815
  }
816
816
 
817
817
  function removeFile(path) {
818
- fetch('/api/config/data/file?filename=' + path, {
818
+ fetch('/api/content/file?filename=' + path, {
819
819
  method: 'DELETE',
820
820
  headers: {
821
821
  'Content-Type': 'application/json',
@@ -890,7 +890,7 @@
890
890
  })
891
891
 
892
892
  phonenumberRemoveButton.addEventListener("click", () => {
893
- fetch('/api/config/phone', {
893
+ fetch('/api/phone', {
894
894
  method: 'DELETE',
895
895
  headers: {
896
896
  'Content-Type': 'application/json',
@@ -917,7 +917,7 @@
917
917
  }, 5000);
918
918
  } else {
919
919
  const mobileNumber = iti.getNumber();
920
- fetch('/api/config/phone?phone_number=' + mobileNumber, {
920
+ fetch('/api/phone?phone_number=' + mobileNumber, {
921
921
  method: 'POST',
922
922
  headers: {
923
923
  'Content-Type': 'application/json',
@@ -970,7 +970,7 @@
970
970
  return;
971
971
  }
972
972
 
973
- fetch('/api/config/phone/verify?code=' + otp, {
973
+ fetch('/api/phone/verify?code=' + otp, {
974
974
  method: 'POST',
975
975
  headers: {
976
976
  'Content-Type': 'application/json',
@@ -36,7 +36,7 @@
36
36
  {% endif %}
37
37
  <div id="khoj-nav-menu" class="khoj-nav-dropdown-content">
38
38
  <div class="khoj-nav-username"> {{ username }} </div>
39
- <a id="settings-nav" class="khoj-nav" href="/config">Settings</a>
39
+ <a id="settings-nav" class="khoj-nav" href="/settings">Settings</a>
40
40
  <a id="github-nav" class="khoj-nav" href="https://github.com/khoj-ai/khoj">GitHub</a>
41
41
  <a id="help-nav" class="khoj-nav" href="https://docs.khoj.dev" target="_blank">Help</a>
42
42
  <a class="khoj-nav" href="/auth/logout">Logout</a>
@@ -19,16 +19,11 @@ class DocxToEntries(TextToEntries):
19
19
  super().__init__()
20
20
 
21
21
  # Define Functions
22
- def process(
23
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
24
- ) -> Tuple[int, int]:
22
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
25
23
  # Extract required fields from config
26
- if not full_corpus:
27
- deletion_file_names = set([file for file in files if files[file] == b""])
28
- files_to_process = set(files) - deletion_file_names
29
- files = {file: files[file] for file in files_to_process}
30
- else:
31
- deletion_file_names = None
24
+ deletion_file_names = set([file for file in files if files[file] == b""])
25
+ files_to_process = set(files) - deletion_file_names
26
+ files = {file: files[file] for file in files_to_process}
32
27
 
33
28
  # Extract Entries from specified Docx files
34
29
  with timer("Extract entries from specified DOCX files", logger):
@@ -48,9 +48,7 @@ class GithubToEntries(TextToEntries):
48
48
  else:
49
49
  return
50
50
 
51
- def process(
52
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
53
- ) -> Tuple[int, int]:
51
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
54
52
  if self.config.pat_token is None or self.config.pat_token == "":
55
53
  logger.error(f"Github PAT token is not set. Skipping github content")
56
54
  raise ValueError("Github PAT token is not set. Skipping github content")
@@ -20,16 +20,11 @@ class ImageToEntries(TextToEntries):
20
20
  super().__init__()
21
21
 
22
22
  # Define Functions
23
- def process(
24
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
25
- ) -> Tuple[int, int]:
23
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
26
24
  # Extract required fields from config
27
- if not full_corpus:
28
- deletion_file_names = set([file for file in files if files[file] == b""])
29
- files_to_process = set(files) - deletion_file_names
30
- files = {file: files[file] for file in files_to_process}
31
- else:
32
- deletion_file_names = None
25
+ deletion_file_names = set([file for file in files if files[file] == b""])
26
+ files_to_process = set(files) - deletion_file_names
27
+ files = {file: files[file] for file in files_to_process}
33
28
 
34
29
  # Extract Entries from specified image files
35
30
  with timer("Extract entries from specified Image files", logger):
@@ -19,16 +19,11 @@ class MarkdownToEntries(TextToEntries):
19
19
  super().__init__()
20
20
 
21
21
  # Define Functions
22
- def process(
23
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
24
- ) -> Tuple[int, int]:
22
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
25
23
  # Extract required fields from config
26
- if not full_corpus:
27
- deletion_file_names = set([file for file in files if files[file] == ""])
28
- files_to_process = set(files) - deletion_file_names
29
- files = {file: files[file] for file in files_to_process}
30
- else:
31
- deletion_file_names = None
24
+ deletion_file_names = set([file for file in files if files[file] == ""])
25
+ files_to_process = set(files) - deletion_file_names
26
+ files = {file: files[file] for file in files_to_process}
32
27
 
33
28
  max_tokens = 256
34
29
  # Extract Entries from specified Markdown files
@@ -78,9 +78,7 @@ class NotionToEntries(TextToEntries):
78
78
 
79
79
  self.body_params = {"page_size": 100}
80
80
 
81
- def process(
82
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
83
- ) -> Tuple[int, int]:
81
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
84
82
  current_entries = []
85
83
 
86
84
  # Get all pages
@@ -20,15 +20,10 @@ class OrgToEntries(TextToEntries):
20
20
  super().__init__()
21
21
 
22
22
  # Define Functions
23
- def process(
24
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
25
- ) -> Tuple[int, int]:
26
- if not full_corpus:
27
- deletion_file_names = set([file for file in files if files[file] == ""])
28
- files_to_process = set(files) - deletion_file_names
29
- files = {file: files[file] for file in files_to_process}
30
- else:
31
- deletion_file_names = None
23
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
24
+ deletion_file_names = set([file for file in files if files[file] == ""])
25
+ files_to_process = set(files) - deletion_file_names
26
+ files = {file: files[file] for file in files_to_process}
32
27
 
33
28
  # Extract Entries from specified Org files
34
29
  max_tokens = 256
@@ -22,16 +22,11 @@ class PdfToEntries(TextToEntries):
22
22
  super().__init__()
23
23
 
24
24
  # Define Functions
25
- def process(
26
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
27
- ) -> Tuple[int, int]:
25
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
28
26
  # Extract required fields from config
29
- if not full_corpus:
30
- deletion_file_names = set([file for file in files if files[file] == b""])
31
- files_to_process = set(files) - deletion_file_names
32
- files = {file: files[file] for file in files_to_process}
33
- else:
34
- deletion_file_names = None
27
+ deletion_file_names = set([file for file in files if files[file] == b""])
28
+ files_to_process = set(files) - deletion_file_names
29
+ files = {file: files[file] for file in files_to_process}
35
30
 
36
31
  # Extract Entries from specified Pdf files
37
32
  with timer("Extract entries from specified PDF files", logger):
@@ -20,15 +20,10 @@ class PlaintextToEntries(TextToEntries):
20
20
  super().__init__()
21
21
 
22
22
  # Define Functions
23
- def process(
24
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
25
- ) -> Tuple[int, int]:
26
- if not full_corpus:
27
- deletion_file_names = set([file for file in files if files[file] == ""])
28
- files_to_process = set(files) - deletion_file_names
29
- files = {file: files[file] for file in files_to_process}
30
- else:
31
- deletion_file_names = None
23
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
24
+ deletion_file_names = set([file for file in files if files[file] == ""])
25
+ files_to_process = set(files) - deletion_file_names
26
+ files = {file: files[file] for file in files_to_process}
32
27
 
33
28
  # Extract Entries from specified plaintext files
34
29
  with timer("Extract entries from specified Plaintext files", logger):
@@ -31,9 +31,7 @@ class TextToEntries(ABC):
31
31
  self.date_filter = DateFilter()
32
32
 
33
33
  @abstractmethod
34
- def process(
35
- self, files: dict[str, str] = None, full_corpus: bool = True, user: KhojUser = None, regenerate: bool = False
36
- ) -> Tuple[int, int]:
34
+ def process(self, files: dict[str, str] = None, user: KhojUser = None, regenerate: bool = False) -> Tuple[int, int]:
37
35
  ...
38
36
 
39
37
  @staticmethod
@@ -68,7 +68,7 @@ async def search_online(
68
68
  logger.info(f"🌐 Searching the Internet for {list(subqueries)}")
69
69
  if send_status_func:
70
70
  subqueries_str = "\n- " + "\n- ".join(list(subqueries))
71
- async for event in send_status_func(f"**🌐 Searching the Internet for**: {subqueries_str}"):
71
+ async for event in send_status_func(f"**Searching the Internet for**: {subqueries_str}"):
72
72
  yield {ChatEvent.STATUS: event}
73
73
 
74
74
  with timer(f"Internet searches for {list(subqueries)} took", logger):
@@ -92,7 +92,7 @@ async def search_online(
92
92
  logger.info(f"🌐👀 Reading web pages at: {list(webpage_links)}")
93
93
  if send_status_func:
94
94
  webpage_links_str = "\n- " + "\n- ".join(list(webpage_links))
95
- async for event in send_status_func(f"**📖 Reading web pages**: {webpage_links_str}"):
95
+ async for event in send_status_func(f"**Reading web pages**: {webpage_links_str}"):
96
96
  yield {ChatEvent.STATUS: event}
97
97
  tasks = [read_webpage_and_extract_content(subquery, link, content) for link, subquery, content in webpages]
98
98
  results = await asyncio.gather(*tasks)
@@ -131,14 +131,14 @@ async def read_webpages(
131
131
  "Infer web pages to read from the query and extract relevant information from them"
132
132
  logger.info(f"Inferring web pages to read")
133
133
  if send_status_func:
134
- async for event in send_status_func(f"**🧐 Inferring web pages to read**"):
134
+ async for event in send_status_func(f"**Inferring web pages to read**"):
135
135
  yield {ChatEvent.STATUS: event}
136
136
  urls = await infer_webpage_urls(query, conversation_history, location)
137
137
 
138
138
  logger.info(f"Reading web pages at: {urls}")
139
139
  if send_status_func:
140
140
  webpage_links_str = "\n- " + "\n- ".join(list(urls))
141
- async for event in send_status_func(f"**📖 Reading web pages**: {webpage_links_str}"):
141
+ async for event in send_status_func(f"**Reading web pages**: {webpage_links_str}"):
142
142
  yield {ChatEvent.STATUS: event}
143
143
  tasks = [read_webpage_and_extract_content(query, url) for url in urls]
144
144
  results = await asyncio.gather(*tasks)