kodit 0.3.16__tar.gz → 0.4.0__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.
- {kodit-0.3.16 → kodit-0.4.0}/Makefile +4 -1
- {kodit-0.3.16 → kodit-0.4.0}/PKG-INFO +1 -1
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/api/index.md +1 -1
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/api/openapi.json +1 -1
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/deployment/index.md +26 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/mcp/index.md +3 -7
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/_version.py +3 -16
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/app.py +11 -2
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/application/services/auto_indexing_service.py +16 -7
- kodit-0.4.0/src/kodit/application/services/indexing_worker_service.py +154 -0
- kodit-0.4.0/src/kodit/application/services/queue_service.py +52 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/application/services/sync_scheduler.py +10 -48
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/cli.py +407 -148
- kodit-0.4.0/src/kodit/cli_utils.py +74 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/config.py +33 -3
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/entities.py +48 -1
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/protocols.py +29 -2
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/value_objects.py +13 -0
- kodit-0.4.0/src/kodit/infrastructure/api/client/__init__.py +14 -0
- kodit-0.4.0/src/kodit/infrastructure/api/client/base.py +100 -0
- kodit-0.4.0/src/kodit/infrastructure/api/client/exceptions.py +21 -0
- kodit-0.4.0/src/kodit/infrastructure/api/client/generated_endpoints.py +27 -0
- kodit-0.4.0/src/kodit/infrastructure/api/client/index_client.py +57 -0
- kodit-0.4.0/src/kodit/infrastructure/api/client/search_client.py +86 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/dependencies.py +13 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/routers/indexes.py +9 -4
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/enrichment/local_enrichment_provider.py +4 -1
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/enrichment/openai_enrichment_provider.py +5 -1
- kodit-0.4.0/src/kodit/infrastructure/enrichment/utils.py +30 -0
- kodit-0.4.0/src/kodit/infrastructure/mappers/task_mapper.py +81 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/sqlalchemy/entities.py +35 -0
- kodit-0.4.0/src/kodit/infrastructure/sqlalchemy/task_repository.py +81 -0
- kodit-0.4.0/src/kodit/migrations/versions/9cf0e87de578_add_queue.py +47 -0
- kodit-0.4.0/src/kodit/utils/generate_api_paths.py +135 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/app_test.py +17 -21
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/application/services/auto_indexing_service_test.py +29 -12
- kodit-0.4.0/tests/kodit/application/services/indexing_worker_service_test.py +412 -0
- kodit-0.4.0/tests/kodit/application/services/queue_service_test.py +146 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/application/services/sync_scheduler_test.py +34 -54
- kodit-0.4.0/tests/kodit/infrastructure/enrichment/utils_test.py +110 -0
- {kodit-0.3.16 → kodit-0.4.0}/.claude/commands/debug.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.claude/commands/new-requirement.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.claude/commands/refactor.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.claude/commands/update-docs.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.claude/settings.json +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.cursor/rules/kodit.mdc +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.cursor/rules/style.mdc +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.dockerignore +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/CODE_OF_CONDUCT.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/CONTRIBUTING.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/dependabot.yml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/workflows/docker.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/workflows/docs.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/workflows/pull_request.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/workflows/pypi-test.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/workflows/pypi.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.github/workflows/test.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.gitignore +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.python-version +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.vscode/launch.json +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/.vscode/settings.json +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/CLAUDE.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/Dockerfile +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/LICENSE +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/README.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/alembic.ini +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/_index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/demos/_index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/demos/go-simple-microservice/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/demos/knock-knock-auth/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/developer/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/getting-started/_index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/getting-started/installation/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/getting-started/integration/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/getting-started/quick-start/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/_index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/api/templates/_content.md.j2 +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/api/templates/_example.md.j2 +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/api/templates/_object_schema.md.j2 +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/api/templates/_security_scheme.md.j2 +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/api/templates/api_doc_template.md.j2 +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/configuration/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/deployment/docker-compose.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/deployment/kubernetes.yaml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/hosted-kodit/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/indexing/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/sync/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/docs/reference/telemetry/index.md +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/pyproject.toml +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/.gitignore +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/application/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/application/factories/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/application/factories/code_indexing_factory.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/application/services/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/application/services/code_indexing_application_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/database.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/errors.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/interfaces.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/services/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/services/bm25_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/services/embedding_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/services/enrichment_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/services/index_query_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/domain/services/index_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/middleware/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/middleware/auth.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/routers/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/routers/search.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/schemas/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/schemas/context.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/schemas/index.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/api/v1/schemas/search.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/bm25/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/bm25/bm25_factory.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/bm25/local_bm25_repository.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/bm25/vectorchord_bm25_repository.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/cloning/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/cloning/git/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/cloning/git/working_copy.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/cloning/metadata.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/embedding_factory.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/embedding_providers/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/embedding_providers/batching.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/embedding_providers/hash_embedding_provider.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/embedding_providers/local_embedding_provider.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/embedding_providers/openai_embedding_provider.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/local_vector_search_repository.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/embedding/vectorchord_vector_search_repository.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/enrichment/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/enrichment/enrichment_factory.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/enrichment/null_enrichment_provider.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/git/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/git/git_utils.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/ignore/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/ignore/ignore_pattern_provider.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/indexing/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/indexing/fusion_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/mappers/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/mappers/index_mapper.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/slicing/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/slicing/language_detection_service.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/slicing/slicer.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/sqlalchemy/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/sqlalchemy/embedding_repository.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/sqlalchemy/index_repository.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/ui/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/ui/progress.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/infrastructure/ui/spinner.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/log.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/mcp.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/middleware.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/README +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/env.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/script.py.mako +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/versions/4073b33f9436_add_file_processing_flag.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/versions/4552eb3f23ce_add_summary.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/versions/7c3bbc2ab32b_add_embeddings_table.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/versions/85155663351e_initial.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/versions/9e53ea8bb3b0_add_authors.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/versions/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/migrations/versions/c3f5137d30f5_index_all_the_things.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/reporting.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/utils/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/utils/dump_openapi.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/src/kodit/utils/path_utils.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/conftest.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/docker-smoke.sh +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/experiments/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/experiments/cline_prompt_tests/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/experiments/cline_prompt_tests/cline_prompt.txt +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/experiments/cline_prompt_tests/cline_prompt_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/application/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/application/code_indexing_application_service_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/application/services/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/cli_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/config_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/bm25_service_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/embedding_service_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/enrichment_service_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/entities_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/language_detection_service_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/services/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/services/index_service_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/domain/value_objects_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/e2e.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/bm25/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/bm25/local_bm25_repository_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/bm25/vectorchord_bm25_repository_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/cloning/git_cloning/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/cloning/git_cloning/working_copy_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/batching_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/embedding_factory_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/embedding_provider/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/embedding_provider/hash_embedding_provider_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/embedding_provider/local_embedding_provider_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/embedding_provider/openai_embedding_provider_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/local_vector_search_repository_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/test_embedding_integration.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/test_openai_socket_providers.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/embedding/vectorchord_vector_search_repository_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/enrichment/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/enrichment/enrichment_factory_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/enrichment/enrichment_provider/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/enrichment/enrichment_provider/local_enrichment_provider_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/enrichment/enrichment_provider/null_enrichment_provider_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/enrichment/enrichment_provider/openai_enrichment_provider_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/mappers/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/mappers/index_mapper_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/c/main.c +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/c/models.c +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/c/models.h +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/c/utils.c +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/c/utils.h +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/cpp/main.cpp +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/cpp/models.cpp +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/cpp/models.hpp +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/cpp/utils.cpp +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/cpp/utils.hpp +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/csharp/Main.cs +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/csharp/Models.cs +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/csharp/Utils.cs +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/css/components.css +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/css/main.css +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/css/utilities.css +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/go/main.go +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/go/models.go +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/go/utils.go +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/html/components.html +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/html/forms.html +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/html/main.html +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/java/Main.java +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/java/Models.java +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/java/Utils.java +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/javascript/main.js +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/javascript/models.js +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/javascript/utils.js +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/python/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/python/main.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/python/models.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/python/utils.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/rust/main.rs +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/rust/models.rs +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/data/rust/utils.rs +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/slicing/slicer_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/snippets/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/snippets/csharp.cs +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/snippets/golang.go +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/snippets/javascript.js +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/snippets/knock_knock_server.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/snippets/python.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/snippets/typescript.tsx +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/sqlalchemy/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/infrastructure/sqlalchemy/embedding_repository_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/log_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/kodit/mcp_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/performance/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/performance/similarity.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/smoke.sh +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/utils/__init__.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/utils/path_utils_test.py +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/tests/vectorchord-smoke.sh +0 -0
- {kodit-0.3.16 → kodit-0.4.0}/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
|
|
@@ -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.
|
|
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.
|
|
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":
|
|
151
|
+
"disabled": false,
|
|
152
152
|
"timeout": 60,
|
|
153
|
-
"
|
|
154
|
-
"
|
|
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.
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
33
|
-
|
|
34
|
-
__commit_id__ = commit_id = None
|
|
20
|
+
__version__ = version = '0.4.0'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 4, 0)
|
|
@@ -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.
|
|
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("
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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.
|
|
11
|
-
|
|
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
|
-
|
|
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("
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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")
|