kodit 0.3.16__tar.gz → 0.3.17__tar.gz

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.

Potentially problematic release.


This version of kodit might be problematic. Click here for more details.

Files changed (279) hide show
  1. {kodit-0.3.16 → kodit-0.3.17}/Makefile +4 -1
  2. {kodit-0.3.16 → kodit-0.3.17}/PKG-INFO +1 -1
  3. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/api/index.md +1 -1
  4. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/api/openapi.json +1 -1
  5. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/deployment/index.md +26 -0
  6. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/mcp/index.md +3 -7
  7. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/_version.py +3 -16
  8. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/app.py +11 -2
  9. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/application/services/auto_indexing_service.py +16 -7
  10. kodit-0.3.17/src/kodit/application/services/indexing_worker_service.py +154 -0
  11. kodit-0.3.17/src/kodit/application/services/queue_service.py +52 -0
  12. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/application/services/sync_scheduler.py +10 -48
  13. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/cli.py +407 -148
  14. kodit-0.3.17/src/kodit/cli_utils.py +74 -0
  15. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/config.py +33 -3
  16. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/entities.py +48 -1
  17. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/protocols.py +29 -2
  18. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/value_objects.py +13 -0
  19. kodit-0.3.17/src/kodit/infrastructure/api/client/__init__.py +14 -0
  20. kodit-0.3.17/src/kodit/infrastructure/api/client/base.py +100 -0
  21. kodit-0.3.17/src/kodit/infrastructure/api/client/exceptions.py +21 -0
  22. kodit-0.3.17/src/kodit/infrastructure/api/client/generated_endpoints.py +27 -0
  23. kodit-0.3.17/src/kodit/infrastructure/api/client/index_client.py +57 -0
  24. kodit-0.3.17/src/kodit/infrastructure/api/client/search_client.py +86 -0
  25. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/dependencies.py +13 -0
  26. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/routers/indexes.py +9 -4
  27. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/enrichment/local_enrichment_provider.py +4 -1
  28. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/enrichment/openai_enrichment_provider.py +5 -1
  29. kodit-0.3.17/src/kodit/infrastructure/enrichment/utils.py +30 -0
  30. kodit-0.3.17/src/kodit/infrastructure/mappers/task_mapper.py +81 -0
  31. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/sqlalchemy/entities.py +35 -0
  32. kodit-0.3.17/src/kodit/infrastructure/sqlalchemy/task_repository.py +81 -0
  33. kodit-0.3.17/src/kodit/migrations/versions/9cf0e87de578_add_queue.py +47 -0
  34. kodit-0.3.17/src/kodit/utils/generate_api_paths.py +135 -0
  35. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/app_test.py +17 -21
  36. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/application/services/auto_indexing_service_test.py +29 -12
  37. kodit-0.3.17/tests/kodit/application/services/indexing_worker_service_test.py +412 -0
  38. kodit-0.3.17/tests/kodit/application/services/queue_service_test.py +146 -0
  39. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/application/services/sync_scheduler_test.py +34 -54
  40. kodit-0.3.17/tests/kodit/infrastructure/enrichment/utils_test.py +110 -0
  41. {kodit-0.3.16 → kodit-0.3.17}/.claude/commands/debug.md +0 -0
  42. {kodit-0.3.16 → kodit-0.3.17}/.claude/commands/new-requirement.md +0 -0
  43. {kodit-0.3.16 → kodit-0.3.17}/.claude/commands/refactor.md +0 -0
  44. {kodit-0.3.16 → kodit-0.3.17}/.claude/commands/update-docs.md +0 -0
  45. {kodit-0.3.16 → kodit-0.3.17}/.claude/settings.json +0 -0
  46. {kodit-0.3.16 → kodit-0.3.17}/.cursor/rules/kodit.mdc +0 -0
  47. {kodit-0.3.16 → kodit-0.3.17}/.cursor/rules/style.mdc +0 -0
  48. {kodit-0.3.16 → kodit-0.3.17}/.dockerignore +0 -0
  49. {kodit-0.3.16 → kodit-0.3.17}/.github/CODE_OF_CONDUCT.md +0 -0
  50. {kodit-0.3.16 → kodit-0.3.17}/.github/CONTRIBUTING.md +0 -0
  51. {kodit-0.3.16 → kodit-0.3.17}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  52. {kodit-0.3.16 → kodit-0.3.17}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  53. {kodit-0.3.16 → kodit-0.3.17}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  54. {kodit-0.3.16 → kodit-0.3.17}/.github/dependabot.yml +0 -0
  55. {kodit-0.3.16 → kodit-0.3.17}/.github/workflows/docker.yaml +0 -0
  56. {kodit-0.3.16 → kodit-0.3.17}/.github/workflows/docs.yaml +0 -0
  57. {kodit-0.3.16 → kodit-0.3.17}/.github/workflows/pull_request.yaml +0 -0
  58. {kodit-0.3.16 → kodit-0.3.17}/.github/workflows/pypi-test.yaml +0 -0
  59. {kodit-0.3.16 → kodit-0.3.17}/.github/workflows/pypi.yaml +0 -0
  60. {kodit-0.3.16 → kodit-0.3.17}/.github/workflows/test.yaml +0 -0
  61. {kodit-0.3.16 → kodit-0.3.17}/.gitignore +0 -0
  62. {kodit-0.3.16 → kodit-0.3.17}/.python-version +0 -0
  63. {kodit-0.3.16 → kodit-0.3.17}/.vscode/launch.json +0 -0
  64. {kodit-0.3.16 → kodit-0.3.17}/.vscode/settings.json +0 -0
  65. {kodit-0.3.16 → kodit-0.3.17}/CLAUDE.md +0 -0
  66. {kodit-0.3.16 → kodit-0.3.17}/Dockerfile +0 -0
  67. {kodit-0.3.16 → kodit-0.3.17}/LICENSE +0 -0
  68. {kodit-0.3.16 → kodit-0.3.17}/README.md +0 -0
  69. {kodit-0.3.16 → kodit-0.3.17}/alembic.ini +0 -0
  70. {kodit-0.3.16 → kodit-0.3.17}/docs/_index.md +0 -0
  71. {kodit-0.3.16 → kodit-0.3.17}/docs/demos/_index.md +0 -0
  72. {kodit-0.3.16 → kodit-0.3.17}/docs/demos/go-simple-microservice/index.md +0 -0
  73. {kodit-0.3.16 → kodit-0.3.17}/docs/demos/knock-knock-auth/index.md +0 -0
  74. {kodit-0.3.16 → kodit-0.3.17}/docs/developer/index.md +0 -0
  75. {kodit-0.3.16 → kodit-0.3.17}/docs/getting-started/_index.md +0 -0
  76. {kodit-0.3.16 → kodit-0.3.17}/docs/getting-started/installation/index.md +0 -0
  77. {kodit-0.3.16 → kodit-0.3.17}/docs/getting-started/integration/index.md +0 -0
  78. {kodit-0.3.16 → kodit-0.3.17}/docs/getting-started/quick-start/index.md +0 -0
  79. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/_index.md +0 -0
  80. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/api/templates/_content.md.j2 +0 -0
  81. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/api/templates/_example.md.j2 +0 -0
  82. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/api/templates/_object_schema.md.j2 +0 -0
  83. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/api/templates/_security_scheme.md.j2 +0 -0
  84. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/api/templates/api_doc_template.md.j2 +0 -0
  85. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/configuration/index.md +0 -0
  86. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/deployment/docker-compose.yaml +0 -0
  87. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/deployment/kubernetes.yaml +0 -0
  88. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/hosted-kodit/index.md +0 -0
  89. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/indexing/index.md +0 -0
  90. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/sync/index.md +0 -0
  91. {kodit-0.3.16 → kodit-0.3.17}/docs/reference/telemetry/index.md +0 -0
  92. {kodit-0.3.16 → kodit-0.3.17}/pyproject.toml +0 -0
  93. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/.gitignore +0 -0
  94. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/__init__.py +0 -0
  95. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/application/__init__.py +0 -0
  96. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/application/factories/__init__.py +0 -0
  97. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/application/factories/code_indexing_factory.py +0 -0
  98. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/application/services/__init__.py +0 -0
  99. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/application/services/code_indexing_application_service.py +0 -0
  100. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/database.py +0 -0
  101. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/__init__.py +0 -0
  102. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/errors.py +0 -0
  103. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/interfaces.py +0 -0
  104. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/services/__init__.py +0 -0
  105. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/services/bm25_service.py +0 -0
  106. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/services/embedding_service.py +0 -0
  107. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/services/enrichment_service.py +0 -0
  108. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/services/index_query_service.py +0 -0
  109. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/domain/services/index_service.py +0 -0
  110. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/__init__.py +0 -0
  111. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/__init__.py +0 -0
  112. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/middleware/__init__.py +0 -0
  113. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/middleware/auth.py +0 -0
  114. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/__init__.py +0 -0
  115. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/routers/__init__.py +0 -0
  116. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/routers/search.py +0 -0
  117. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/schemas/__init__.py +0 -0
  118. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/schemas/context.py +0 -0
  119. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/schemas/index.py +0 -0
  120. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/api/v1/schemas/search.py +0 -0
  121. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/bm25/__init__.py +0 -0
  122. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/bm25/bm25_factory.py +0 -0
  123. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/bm25/local_bm25_repository.py +0 -0
  124. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/bm25/vectorchord_bm25_repository.py +0 -0
  125. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/cloning/__init__.py +0 -0
  126. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/cloning/git/__init__.py +0 -0
  127. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/cloning/git/working_copy.py +0 -0
  128. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/cloning/metadata.py +0 -0
  129. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/__init__.py +0 -0
  130. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/embedding_factory.py +0 -0
  131. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/embedding_providers/__init__.py +0 -0
  132. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/embedding_providers/batching.py +0 -0
  133. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/embedding_providers/hash_embedding_provider.py +0 -0
  134. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/embedding_providers/local_embedding_provider.py +0 -0
  135. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/embedding_providers/openai_embedding_provider.py +0 -0
  136. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/local_vector_search_repository.py +0 -0
  137. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/embedding/vectorchord_vector_search_repository.py +0 -0
  138. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/enrichment/__init__.py +0 -0
  139. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/enrichment/enrichment_factory.py +0 -0
  140. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/enrichment/null_enrichment_provider.py +0 -0
  141. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/git/__init__.py +0 -0
  142. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/git/git_utils.py +0 -0
  143. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/ignore/__init__.py +0 -0
  144. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/ignore/ignore_pattern_provider.py +0 -0
  145. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/indexing/__init__.py +0 -0
  146. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/indexing/fusion_service.py +0 -0
  147. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/mappers/__init__.py +0 -0
  148. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/mappers/index_mapper.py +0 -0
  149. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/slicing/__init__.py +0 -0
  150. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/slicing/language_detection_service.py +0 -0
  151. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/slicing/slicer.py +0 -0
  152. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/sqlalchemy/__init__.py +0 -0
  153. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/sqlalchemy/embedding_repository.py +0 -0
  154. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/sqlalchemy/index_repository.py +0 -0
  155. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/ui/__init__.py +0 -0
  156. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/ui/progress.py +0 -0
  157. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/infrastructure/ui/spinner.py +0 -0
  158. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/log.py +0 -0
  159. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/mcp.py +0 -0
  160. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/middleware.py +0 -0
  161. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/README +0 -0
  162. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/__init__.py +0 -0
  163. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/env.py +0 -0
  164. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/script.py.mako +0 -0
  165. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/versions/4073b33f9436_add_file_processing_flag.py +0 -0
  166. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/versions/4552eb3f23ce_add_summary.py +0 -0
  167. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/versions/7c3bbc2ab32b_add_embeddings_table.py +0 -0
  168. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/versions/85155663351e_initial.py +0 -0
  169. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/versions/9e53ea8bb3b0_add_authors.py +0 -0
  170. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/versions/__init__.py +0 -0
  171. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/migrations/versions/c3f5137d30f5_index_all_the_things.py +0 -0
  172. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/reporting.py +0 -0
  173. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/utils/__init__.py +0 -0
  174. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/utils/dump_openapi.py +0 -0
  175. {kodit-0.3.16 → kodit-0.3.17}/src/kodit/utils/path_utils.py +0 -0
  176. {kodit-0.3.16 → kodit-0.3.17}/tests/__init__.py +0 -0
  177. {kodit-0.3.16 → kodit-0.3.17}/tests/conftest.py +0 -0
  178. {kodit-0.3.16 → kodit-0.3.17}/tests/docker-smoke.sh +0 -0
  179. {kodit-0.3.16 → kodit-0.3.17}/tests/experiments/__init__.py +0 -0
  180. {kodit-0.3.16 → kodit-0.3.17}/tests/experiments/cline_prompt_tests/__init__.py +0 -0
  181. {kodit-0.3.16 → kodit-0.3.17}/tests/experiments/cline_prompt_tests/cline_prompt.txt +0 -0
  182. {kodit-0.3.16 → kodit-0.3.17}/tests/experiments/cline_prompt_tests/cline_prompt_test.py +0 -0
  183. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/__init__.py +0 -0
  184. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/application/__init__.py +0 -0
  185. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/application/code_indexing_application_service_test.py +0 -0
  186. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/application/services/__init__.py +0 -0
  187. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/cli_test.py +0 -0
  188. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/config_test.py +0 -0
  189. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/__init__.py +0 -0
  190. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/bm25_service_test.py +0 -0
  191. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/embedding_service_test.py +0 -0
  192. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/enrichment_service_test.py +0 -0
  193. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/entities_test.py +0 -0
  194. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/language_detection_service_test.py +0 -0
  195. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/services/__init__.py +0 -0
  196. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/services/index_service_test.py +0 -0
  197. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/domain/value_objects_test.py +0 -0
  198. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/e2e.py +0 -0
  199. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/__init__.py +0 -0
  200. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/bm25/__init__.py +0 -0
  201. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/bm25/local_bm25_repository_test.py +0 -0
  202. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/bm25/vectorchord_bm25_repository_test.py +0 -0
  203. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/cloning/git_cloning/__init__.py +0 -0
  204. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/cloning/git_cloning/working_copy_test.py +0 -0
  205. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/__init__.py +0 -0
  206. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/batching_test.py +0 -0
  207. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/embedding_factory_test.py +0 -0
  208. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/embedding_provider/__init__.py +0 -0
  209. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/embedding_provider/hash_embedding_provider_test.py +0 -0
  210. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/embedding_provider/local_embedding_provider_test.py +0 -0
  211. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/embedding_provider/openai_embedding_provider_test.py +0 -0
  212. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/local_vector_search_repository_test.py +0 -0
  213. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/test_embedding_integration.py +0 -0
  214. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/test_openai_socket_providers.py +0 -0
  215. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/embedding/vectorchord_vector_search_repository_test.py +0 -0
  216. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/enrichment/__init__.py +0 -0
  217. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/enrichment/enrichment_factory_test.py +0 -0
  218. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/enrichment/enrichment_provider/__init__.py +0 -0
  219. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/enrichment/enrichment_provider/local_enrichment_provider_test.py +0 -0
  220. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/enrichment/enrichment_provider/null_enrichment_provider_test.py +0 -0
  221. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/enrichment/enrichment_provider/openai_enrichment_provider_test.py +0 -0
  222. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/mappers/__init__.py +0 -0
  223. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/mappers/index_mapper_test.py +0 -0
  224. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/__init__.py +0 -0
  225. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/__init__.py +0 -0
  226. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/c/main.c +0 -0
  227. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/c/models.c +0 -0
  228. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/c/models.h +0 -0
  229. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/c/utils.c +0 -0
  230. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/c/utils.h +0 -0
  231. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/cpp/main.cpp +0 -0
  232. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/cpp/models.cpp +0 -0
  233. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/cpp/models.hpp +0 -0
  234. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/cpp/utils.cpp +0 -0
  235. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/cpp/utils.hpp +0 -0
  236. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/csharp/Main.cs +0 -0
  237. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/csharp/Models.cs +0 -0
  238. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/csharp/Utils.cs +0 -0
  239. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/css/components.css +0 -0
  240. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/css/main.css +0 -0
  241. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/css/utilities.css +0 -0
  242. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/go/main.go +0 -0
  243. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/go/models.go +0 -0
  244. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/go/utils.go +0 -0
  245. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/html/components.html +0 -0
  246. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/html/forms.html +0 -0
  247. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/html/main.html +0 -0
  248. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/java/Main.java +0 -0
  249. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/java/Models.java +0 -0
  250. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/java/Utils.java +0 -0
  251. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/javascript/main.js +0 -0
  252. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/javascript/models.js +0 -0
  253. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/javascript/utils.js +0 -0
  254. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/python/__init__.py +0 -0
  255. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/python/main.py +0 -0
  256. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/python/models.py +0 -0
  257. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/python/utils.py +0 -0
  258. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/rust/main.rs +0 -0
  259. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/rust/models.rs +0 -0
  260. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/data/rust/utils.rs +0 -0
  261. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/slicing/slicer_test.py +0 -0
  262. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/snippets/__init__.py +0 -0
  263. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/snippets/csharp.cs +0 -0
  264. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/snippets/golang.go +0 -0
  265. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/snippets/javascript.js +0 -0
  266. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/snippets/knock_knock_server.py +0 -0
  267. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/snippets/python.py +0 -0
  268. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/snippets/typescript.tsx +0 -0
  269. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/sqlalchemy/__init__.py +0 -0
  270. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/infrastructure/sqlalchemy/embedding_repository_test.py +0 -0
  271. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/log_test.py +0 -0
  272. {kodit-0.3.16 → kodit-0.3.17}/tests/kodit/mcp_test.py +0 -0
  273. {kodit-0.3.16 → kodit-0.3.17}/tests/performance/__init__.py +0 -0
  274. {kodit-0.3.16 → kodit-0.3.17}/tests/performance/similarity.py +0 -0
  275. {kodit-0.3.16 → kodit-0.3.17}/tests/smoke.sh +0 -0
  276. {kodit-0.3.16 → kodit-0.3.17}/tests/utils/__init__.py +0 -0
  277. {kodit-0.3.16 → kodit-0.3.17}/tests/utils/path_utils_test.py +0 -0
  278. {kodit-0.3.16 → kodit-0.3.17}/tests/vectorchord-smoke.sh +0 -0
  279. {kodit-0.3.16 → kodit-0.3.17}/uv.lock +0 -0
@@ -10,11 +10,14 @@ openapi: build
10
10
  openapi-check: openapi
11
11
  git diff --exit-code docs/reference/api/index.md
12
12
 
13
+ generate-api-paths: openapi
14
+ uv run python src/kodit/utils/generate_api_paths.py
15
+
13
16
  type:
14
17
  uv run mypy --config-file pyproject.toml .
15
18
 
16
19
  lint:
17
20
  uv run ruff check --fix --unsafe-fixes
18
21
 
19
- test: lint type
22
+ test: lint type openapi-check
20
23
  uv run pytest -s --cov=src --cov-report=xml tests/kodit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kodit
3
- Version: 0.3.16
3
+ Version: 0.3.17
4
4
  Summary: Code indexing for better AI code generation
5
5
  Project-URL: Homepage, https://docs.helixml.tech/kodit/
6
6
  Project-URL: Documentation, https://docs.helixml.tech/kodit/
@@ -12,7 +12,7 @@ look at the [hosted version](https://kodit.helix.ml/docs).
12
12
  This is the REST API for the Kodit server. Please refer to the
13
13
  [Kodit documentation](https://docs.helix.ml/kodit/) for more information.
14
14
 
15
- Current version: 0.3.16
15
+ Current version: 0.3.17
16
16
 
17
17
  ## Authentication
18
18
 
@@ -3,7 +3,7 @@
3
3
  "info": {
4
4
  "title": "kodit API",
5
5
  "description": "\nThis is the REST API for the Kodit server. Please refer to the\n[Kodit documentation](https://docs.helix.ml/kodit/) for more information.\n ",
6
- "version": "0.3.16"
6
+ "version": "0.3.17"
7
7
  },
8
8
  "paths": {
9
9
  "/healthz": {
@@ -32,3 +32,29 @@ Deploy with `kubectl -n kodit apply -f kubernetes.yaml`
32
32
 
33
33
  1. `kind create cluster`
34
34
  2. `kubectl -n kodit apply -f kubernetes.yaml`
35
+
36
+ ## Remote CLI Access
37
+
38
+ Once you have Kodit deployed as a server, you can connect to it remotely using the [REST
39
+ API](../api/index.md) or the Kodit CLI (which uses the REST API).
40
+
41
+ ### Configuration
42
+
43
+ Remote mode is activated when you configure a server URL. You can do this via environment variables or CLI flags:
44
+
45
+ **Environment Variables:**
46
+
47
+ ```bash
48
+ export REMOTE_SERVER_URL=https://your-kodit-server.com
49
+ export REMOTE_API_KEY=your-api-key-here # Optional: Only if you have API key's enabled
50
+ export REMOTE_TIMEOUT=60.0 # Optional: request timeout in seconds
51
+ export REMOTE_MAX_RETRIES=5 # Optional: max retry attempts
52
+ export REMOTE_VERIFY_SSL=true # Optional: verify SSL certificates
53
+ ```
54
+
55
+ ### Security
56
+
57
+ - Always use HTTPS in production environments
58
+ - Store API keys securely and never commit them to version control
59
+ - Use environment variables or secure credential stores for API keys
60
+ - The CLI verifies SSL certificates by default (can be disabled with `REMOTE_VERIFY_SSL=false`)
@@ -148,19 +148,15 @@ Add the following configuration:
148
148
  "mcpServers": {
149
149
  "kodit": {
150
150
  "autoApprove": [],
151
- "disabled": true,
151
+ "disabled": false,
152
152
  "timeout": 60,
153
- "url": "https://kodit.helix.ml/mcp",
154
- "transportType": "http"
153
+ "type": "streamableHttp",
154
+ "url": "https://kodit.helix.ml/mcp"
155
155
  }
156
156
  }
157
157
  }
158
158
  ```
159
159
 
160
- Note that some cline users are still [reporting issues with HTTP
161
- streaming](https://github.com/cline/cline/issues/3315), so you may need to use sse
162
- instead.
163
-
164
160
  #### Cline STDIO Mode
165
161
 
166
162
  For STDIO mode, please use:
@@ -1,14 +1,7 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = [
5
- "__version__",
6
- "__version_tuple__",
7
- "version",
8
- "version_tuple",
9
- "__commit_id__",
10
- "commit_id",
11
- ]
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
12
5
 
13
6
  TYPE_CHECKING = False
14
7
  if TYPE_CHECKING:
@@ -16,19 +9,13 @@ if TYPE_CHECKING:
16
9
  from typing import Union
17
10
 
18
11
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
- COMMIT_ID = Union[str, None]
20
12
  else:
21
13
  VERSION_TUPLE = object
22
- COMMIT_ID = object
23
14
 
24
15
  version: str
25
16
  __version__: str
26
17
  __version_tuple__: VERSION_TUPLE
27
18
  version_tuple: VERSION_TUPLE
28
- commit_id: COMMIT_ID
29
- __commit_id__: COMMIT_ID
30
19
 
31
- __version__ = version = '0.3.16'
32
- __version_tuple__ = version_tuple = (0, 3, 16)
33
-
34
- __commit_id__ = commit_id = None
20
+ __version__ = version = '0.3.17'
21
+ __version_tuple__ = version_tuple = (0, 3, 17)
@@ -9,6 +9,7 @@ from fastapi.responses import RedirectResponse
9
9
 
10
10
  from kodit._version import version
11
11
  from kodit.application.services.auto_indexing_service import AutoIndexingService
12
+ from kodit.application.services.indexing_worker_service import IndexingWorkerService
12
13
  from kodit.application.services.sync_scheduler import SyncSchedulerService
13
14
  from kodit.config import AppContext
14
15
  from kodit.infrastructure.api.v1.routers import indexes_router, search_router
@@ -28,9 +29,16 @@ async def app_lifespan(_: FastAPI) -> AsyncIterator[AppLifespanState]:
28
29
 
29
30
  # App context has already been configured by the CLI.
30
31
  app_context = AppContext()
32
+ db = await app_context.get_db()
33
+
34
+ # Start the queue worker service
35
+ _indexing_worker_service = IndexingWorkerService(
36
+ app_context=app_context,
37
+ session_factory=db.session_factory,
38
+ )
39
+ await _indexing_worker_service.start()
31
40
 
32
41
  # Start auto-indexing service
33
- db = await app_context.get_db()
34
42
  _auto_indexing_service = AutoIndexingService(
35
43
  app_context=app_context,
36
44
  session_factory=db.session_factory,
@@ -40,7 +48,6 @@ async def app_lifespan(_: FastAPI) -> AsyncIterator[AppLifespanState]:
40
48
  # Start sync scheduler service
41
49
  if app_context.periodic_sync.enabled:
42
50
  _sync_scheduler_service = SyncSchedulerService(
43
- app_context=app_context,
44
51
  session_factory=db.session_factory,
45
52
  )
46
53
  _sync_scheduler_service.start_periodic_sync(
@@ -54,6 +61,8 @@ async def app_lifespan(_: FastAPI) -> AsyncIterator[AppLifespanState]:
54
61
  await _sync_scheduler_service.stop_periodic_sync()
55
62
  if _auto_indexing_service:
56
63
  await _auto_indexing_service.stop()
64
+ if _indexing_worker_service:
65
+ await _indexing_worker_service.stop()
57
66
 
58
67
 
59
68
  # See https://gofastmcp.com/integrations/fastapi#mounting-an-mcp-server
@@ -1,6 +1,7 @@
1
1
  """Service for automatically indexing configured sources."""
2
2
 
3
3
  import asyncio
4
+ import warnings
4
5
  from collections.abc import Callable
5
6
  from contextlib import suppress
6
7
 
@@ -10,8 +11,10 @@ from sqlalchemy.ext.asyncio import AsyncSession
10
11
  from kodit.application.factories.code_indexing_factory import (
11
12
  create_code_indexing_application_service,
12
13
  )
14
+ from kodit.application.services.queue_service import QueueService
13
15
  from kodit.config import AppContext
14
- from kodit.infrastructure.ui.progress import create_log_progress_callback
16
+ from kodit.domain.entities import Task
17
+ from kodit.domain.value_objects import QueuePriority
15
18
 
16
19
 
17
20
  class AutoIndexingService:
@@ -37,6 +40,12 @@ class AutoIndexingService:
37
40
  self.log.info("Auto-indexing is disabled (no sources configured)")
38
41
  return
39
42
 
43
+ warnings.warn(
44
+ "Auto-indexing is deprecated and will be removed in a future version, please use the API to index sources.", # noqa: E501
45
+ DeprecationWarning,
46
+ stacklevel=2,
47
+ )
48
+
40
49
  auto_sources = [source.uri for source in self.app_context.auto_indexing.sources]
41
50
  self.log.info("Starting background indexing", num_sources=len(auto_sources))
42
51
  self._indexing_task = asyncio.create_task(self._index_sources(auto_sources))
@@ -44,6 +53,7 @@ class AutoIndexingService:
44
53
  async def _index_sources(self, sources: list[str]) -> None:
45
54
  """Index all configured sources in the background."""
46
55
  async with self.session_factory() as session:
56
+ queue_service = QueueService(session=session)
47
57
  service = create_code_indexing_application_service(
48
58
  app_context=self.app_context,
49
59
  session=session,
@@ -56,18 +66,17 @@ class AutoIndexingService:
56
66
  self.log.info("Index already exists, skipping", source=source)
57
67
  continue
58
68
 
59
- self.log.info("Auto-indexing source", source=source)
69
+ self.log.info("Adding auto-indexing task to queue", source=source)
60
70
 
61
71
  # Create index
62
72
  index = await service.create_index_from_uri(source)
63
73
 
64
- # Run indexing (without progress callback for background mode)
65
- await service.run_index(
66
- index, progress_callback=create_log_progress_callback()
74
+ await queue_service.enqueue_task(
75
+ Task.create_index_update_task(
76
+ index.id, QueuePriority.BACKGROUND
77
+ )
67
78
  )
68
79
 
69
- self.log.info("Successfully auto-indexed source", source=source)
70
-
71
80
  except Exception as exc:
72
81
  self.log.exception(
73
82
  "Failed to auto-index source", source=source, error=str(exc)
@@ -0,0 +1,154 @@
1
+ """Service for processing indexing tasks from the database queue."""
2
+
3
+ import asyncio
4
+ from collections.abc import Callable
5
+ from concurrent.futures import ThreadPoolExecutor
6
+ from contextlib import suppress
7
+ from datetime import UTC, datetime
8
+
9
+ import structlog
10
+ from sqlalchemy.ext.asyncio import AsyncSession
11
+
12
+ from kodit.application.factories.code_indexing_factory import (
13
+ create_code_indexing_application_service,
14
+ )
15
+ from kodit.config import AppContext
16
+ from kodit.domain.entities import Task
17
+ from kodit.domain.value_objects import TaskType
18
+ from kodit.infrastructure.sqlalchemy.task_repository import SqlAlchemyTaskRepository
19
+
20
+
21
+ class IndexingWorkerService:
22
+ """Service for processing indexing tasks from the database queue.
23
+
24
+ This worker polls the database for pending tasks and processes the heavy
25
+ indexing work in separate threads to prevent blocking API responsiveness.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ app_context: AppContext,
31
+ session_factory: Callable[[], AsyncSession],
32
+ ) -> None:
33
+ """Initialize the indexing worker service."""
34
+ self.app_context = app_context
35
+ self.session_factory = session_factory
36
+ self._worker_task: asyncio.Task | None = None
37
+ self._shutdown_event = asyncio.Event()
38
+ self._executor = ThreadPoolExecutor(
39
+ max_workers=1, thread_name_prefix="indexing-worker"
40
+ )
41
+ self.log = structlog.get_logger(__name__)
42
+
43
+ async def start(self) -> None:
44
+ """Start the worker to process the queue."""
45
+ self._running = True
46
+
47
+ # Start single worker task
48
+ self._worker_task = asyncio.create_task(self._worker_loop())
49
+
50
+ self.log.info(
51
+ "Indexing worker started",
52
+ )
53
+
54
+ async def stop(self) -> None:
55
+ """Stop the worker gracefully."""
56
+ self.log.info("Stopping indexing worker")
57
+ self._shutdown_event.set()
58
+
59
+ if self._worker_task and not self._worker_task.done():
60
+ self._worker_task.cancel()
61
+ with suppress(asyncio.CancelledError):
62
+ await self._worker_task
63
+
64
+ # Shutdown the thread pool executor
65
+ self._executor.shutdown(wait=True)
66
+
67
+ self.log.info("Indexing worker stopped")
68
+
69
+ async def _worker_loop(self) -> None:
70
+ self.log.debug("Worker loop started")
71
+
72
+ while not self._shutdown_event.is_set():
73
+ try:
74
+ async with self.session_factory() as session:
75
+ repo = SqlAlchemyTaskRepository(session)
76
+ task = await repo.take()
77
+ await session.commit()
78
+
79
+ # If there's a task, process it in a new thread
80
+ if task:
81
+ await asyncio.get_event_loop().run_in_executor(
82
+ self._executor, self._process_task, task
83
+ )
84
+ continue
85
+
86
+ # If no task, sleep for a bit
87
+ await asyncio.sleep(1)
88
+ continue
89
+
90
+ except Exception as e:
91
+ self.log.exception(
92
+ "Error processing task",
93
+ error=str(e),
94
+ )
95
+ continue
96
+
97
+ self.log.info("Worker loop stopped")
98
+
99
+ def _process_task(self, task: Task) -> None:
100
+ """Process a single task."""
101
+ self.log.info(
102
+ "Processing task",
103
+ task_id=task.id,
104
+ task_type=task.type.value,
105
+ )
106
+
107
+ start_time = datetime.now(UTC)
108
+
109
+ # Create a new event loop for this thread
110
+ loop = asyncio.new_event_loop()
111
+ asyncio.set_event_loop(loop)
112
+
113
+ try:
114
+ # Process based on task type (currently only INDEX_UPDATE is supported)
115
+ if task.type is TaskType.INDEX_UPDATE:
116
+ loop.run_until_complete(self._process_index_update(task))
117
+ else:
118
+ self.log.warning(
119
+ "Unknown task type",
120
+ task_id=task.id,
121
+ task_type=task.type,
122
+ )
123
+ return
124
+ finally:
125
+ loop.close()
126
+
127
+ duration = (datetime.now(UTC) - start_time).total_seconds()
128
+ self.log.info(
129
+ "Task completed successfully",
130
+ task_id=task.id,
131
+ duration_seconds=duration,
132
+ )
133
+
134
+ async def _process_index_update(self, task: Task) -> None:
135
+ """Process index update/sync task."""
136
+ index_id = task.payload.get("index_id")
137
+ if not index_id:
138
+ raise ValueError("Missing index_id in task payload")
139
+
140
+ # Create a fresh database connection for this thread's event loop
141
+ db = await self.app_context.new_db(run_migrations=True)
142
+ try:
143
+ async with db.session_factory() as session:
144
+ service = create_code_indexing_application_service(
145
+ app_context=self.app_context,
146
+ session=session,
147
+ )
148
+ index = await service.index_repository.get(index_id)
149
+ if not index:
150
+ raise ValueError(f"Index not found: {index_id}")
151
+
152
+ await service.run_index(index)
153
+ finally:
154
+ await db.close()
@@ -0,0 +1,52 @@
1
+ """Queue service for managing tasks."""
2
+
3
+ import structlog
4
+ from sqlalchemy.ext.asyncio import AsyncSession
5
+
6
+ from kodit.domain.entities import Task
7
+ from kodit.domain.value_objects import TaskType
8
+ from kodit.infrastructure.sqlalchemy.task_repository import SqlAlchemyTaskRepository
9
+
10
+
11
+ class QueueService:
12
+ """Service for queue operations using database persistence.
13
+
14
+ This service provides the main interface for enqueuing and managing tasks.
15
+ It uses the existing Task entity in the database with a flexible JSON payload.
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ session: AsyncSession,
21
+ ) -> None:
22
+ """Initialize the queue service."""
23
+ self.session = session
24
+ self.log = structlog.get_logger(__name__)
25
+
26
+ async def enqueue_task(self, task: Task) -> None:
27
+ """Queue a task in the database."""
28
+ repo = SqlAlchemyTaskRepository(self.session)
29
+
30
+ # See if task already exists
31
+ db_task = await repo.get(task.id)
32
+ if db_task:
33
+ # Task already exists, update priority
34
+ db_task.priority = task.priority
35
+ await repo.update(db_task)
36
+ self.log.info("Task updated", task_id=task.id, task_type=task.type)
37
+ else:
38
+ # Otherwise, add task
39
+ await repo.add(task)
40
+ self.log.info(
41
+ "Task queued",
42
+ task_id=task.id,
43
+ task_type=task.type,
44
+ payload=task.payload,
45
+ )
46
+
47
+ await self.session.commit()
48
+
49
+ async def list_tasks(self, task_type: TaskType | None = None) -> list[Task]:
50
+ """List all tasks in the queue."""
51
+ repo = SqlAlchemyTaskRepository(self.session)
52
+ return await repo.list(task_type)
@@ -7,14 +7,12 @@ from contextlib import suppress
7
7
  import structlog
8
8
  from sqlalchemy.ext.asyncio import AsyncSession
9
9
 
10
- from kodit.application.factories.code_indexing_factory import (
11
- create_code_indexing_application_service,
12
- )
13
- from kodit.config import AppContext
10
+ from kodit.application.services.queue_service import QueueService
11
+ from kodit.domain.entities import Task
14
12
  from kodit.domain.services.index_query_service import IndexQueryService
13
+ from kodit.domain.value_objects import QueuePriority
15
14
  from kodit.infrastructure.indexing.fusion_service import ReciprocalRankFusionService
16
15
  from kodit.infrastructure.sqlalchemy.index_repository import SqlAlchemyIndexRepository
17
- from kodit.infrastructure.ui.progress import create_log_progress_callback
18
16
 
19
17
 
20
18
  class SyncSchedulerService:
@@ -22,11 +20,9 @@ class SyncSchedulerService:
22
20
 
23
21
  def __init__(
24
22
  self,
25
- app_context: AppContext,
26
23
  session_factory: Callable[[], AsyncSession],
27
24
  ) -> None:
28
25
  """Initialize the sync scheduler service."""
29
- self.app_context = app_context
30
26
  self.session_factory = session_factory
31
27
  self.log = structlog.get_logger(__name__)
32
28
  self._sync_task: asyncio.Task | None = None
@@ -73,10 +69,7 @@ class SyncSchedulerService:
73
69
 
74
70
  async with self.session_factory() as session:
75
71
  # Create services
76
- service = create_code_indexing_application_service(
77
- app_context=self.app_context,
78
- session=session,
79
- )
72
+ queue_service = QueueService(session=session)
80
73
  index_query_service = IndexQueryService(
81
74
  index_repository=SqlAlchemyIndexRepository(session=session),
82
75
  fusion_service=ReciprocalRankFusionService(),
@@ -89,43 +82,12 @@ class SyncSchedulerService:
89
82
  self.log.info("No indexes found to sync")
90
83
  return
91
84
 
92
- self.log.info("Syncing indexes", count=len(all_indexes))
93
-
94
- success_count = 0
95
- failure_count = 0
85
+ self.log.info("Adding sync tasks to queue", count=len(all_indexes))
96
86
 
97
87
  # Sync each index
98
88
  for index in all_indexes:
99
- try:
100
- self.log.info(
101
- "Syncing index",
102
- index_id=index.id,
103
- source=str(index.source.working_copy.remote_uri),
104
- )
105
-
106
- await service.run_index(
107
- index, progress_callback=create_log_progress_callback()
108
- )
109
- success_count += 1
110
-
111
- self.log.info(
112
- "Index sync completed",
113
- index_id=index.id,
114
- source=str(index.source.working_copy.remote_uri),
115
- )
116
-
117
- except Exception as e:
118
- failure_count += 1
119
- self.log.exception(
120
- "Index sync failed",
121
- index_id=index.id,
122
- source=str(index.source.working_copy.remote_uri),
123
- error=e,
124
- )
125
-
126
- self.log.info(
127
- "Sync operation completed",
128
- total=len(all_indexes),
129
- success=success_count,
130
- failures=failure_count,
131
- )
89
+ await queue_service.enqueue_task(
90
+ Task.create_index_update_task(index.id, QueuePriority.BACKGROUND)
91
+ )
92
+
93
+ self.log.info("Sync operation completed")