kodit 0.1.3__tar.gz → 0.1.4__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.1.4/.cursor/rules/kodit.mdc +6 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/workflows/pypi.yaml +20 -3
- {kodit-0.1.3 → kodit-0.1.4}/PKG-INFO +1 -1
- kodit-0.1.4/docs/_index.md +92 -0
- kodit-0.1.4/docs/developer/index.md +30 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/_version.py +2 -2
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/cli.py +0 -2
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/database.py +2 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/indexing/service.py +0 -1
- kodit-0.1.4/src/kodit/mcp.py +110 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/mcp_test.py +43 -0
- kodit-0.1.3/docs/_index.md +0 -53
- kodit-0.1.3/docs/developer/index.md +0 -17
- kodit-0.1.3/src/kodit/mcp.py +0 -51
- {kodit-0.1.3 → kodit-0.1.4}/.github/CODE_OF_CONDUCT.md +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/CONTRIBUTING.md +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/workflows/docker.yaml +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/workflows/docs.yaml +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/workflows/pypi-test.yaml +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.github/workflows/test.yaml +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.gitignore +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.python-version +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/.vscode/settings.json +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/Dockerfile +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/LICENSE +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/README.md +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/alembic.ini +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/pyproject.toml +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/.gitignore +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/alembic/README +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/alembic/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/alembic/env.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/alembic/script.py.mako +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/alembic/versions/85155663351e_initial.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/alembic/versions/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/app.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/config.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/indexing/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/indexing/models.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/indexing/repository.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/logging.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/middleware.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/retreival/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/retreival/repository.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/retreival/service.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/sources/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/sources/models.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/sources/repository.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/sources/service.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/src/kodit/sse.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/conftest.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/cli_test.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/indexing/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/indexing/test_service.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/retreival/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/retreival/test_service.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/sources/__init__.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/kodit/sources/test_service.py +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/tests/smoke.sh +0 -0
- {kodit-0.1.3 → kodit-0.1.4}/uv.lock +0 -0
|
@@ -28,10 +28,27 @@ jobs:
|
|
|
28
28
|
steps:
|
|
29
29
|
- name: Wait for PyPI release to be available
|
|
30
30
|
run: |
|
|
31
|
+
set -x
|
|
32
|
+
|
|
33
|
+
REPO_NAME=${{ github.event.repository.name }}
|
|
34
|
+
REPO_TAG=${{ github.event.release.tag_name }}
|
|
35
|
+
REPO_TAG=0.1.3
|
|
36
|
+
|
|
37
|
+
# Get the first letter of the repo name
|
|
38
|
+
REPO_NAME_FIRST_LETTER=${REPO_NAME:0:1}
|
|
39
|
+
|
|
40
|
+
# Initialize counter for 60 second timeout
|
|
41
|
+
count=0
|
|
31
42
|
while true; do
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
if curl -sfL https://pypi.io/packages/source/${REPO_NAME_FIRST_LETTER}/${REPO_NAME}/${REPO_NAME}-${REPO_TAG}.tar.gz > /dev/null; then
|
|
44
|
+
break
|
|
45
|
+
fi
|
|
46
|
+
sleep 1
|
|
47
|
+
((count++))
|
|
48
|
+
if [ $count -ge 60 ]; then
|
|
49
|
+
echo "Timeout reached after 60 seconds"
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
35
52
|
done
|
|
36
53
|
- uses: mislav/bump-homebrew-formula-action@v3
|
|
37
54
|
with:
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "kodit: Code Indexing MCP Server"
|
|
3
|
+
linkTitle: kodit Docs
|
|
4
|
+
cascade:
|
|
5
|
+
type: docs
|
|
6
|
+
menu:
|
|
7
|
+
main:
|
|
8
|
+
name: kodit Docs
|
|
9
|
+
weight: 3
|
|
10
|
+
# next: /helix/getting-started
|
|
11
|
+
weight: 1
|
|
12
|
+
aliases:
|
|
13
|
+
- /coda
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Please choose your preferred installation method. They all ultimately install the kodit
|
|
19
|
+
cli, which contains the kodit MCP server and other tools to manage your data sources.
|
|
20
|
+
|
|
21
|
+
### Docker
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
docker run -it --rm registry.helix.ml/helix/kodit:latest
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Always replace latest with a specific version.
|
|
28
|
+
|
|
29
|
+
### pipx
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
pipx install kodit
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### homebrew
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
brew install helixml/kodit/kodit
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### uv
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
uv tool install kodit
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### pip
|
|
48
|
+
|
|
49
|
+
Use this if you want to use kodit as a python library:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pip install kodit
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
Kodit has two key parts. A configuration CLI to manage what gets indexed and an MCP
|
|
58
|
+
server to expose your code to an AI coding assistant.
|
|
59
|
+
|
|
60
|
+
1. Add a source: `kodit sources create /path/to/your/code`
|
|
61
|
+
2. Create an index on that source: `kodit indexes create 1`
|
|
62
|
+
3. Test retrieval on your index: `kodit retrieve "test"`
|
|
63
|
+
4. Start an MCP server: `kodit serve`
|
|
64
|
+
|
|
65
|
+
Now browse to your AI coding assistant and add the MCP server. You will also need to
|
|
66
|
+
tell your assistant to use this server in coding tasks, otherwise it won't get called!
|
|
67
|
+
|
|
68
|
+
### Integration with Cursor
|
|
69
|
+
|
|
70
|
+
Add the following to `.cursor/mcp.json`:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"code-search": {
|
|
76
|
+
"url": "http://localhost:8080/sse"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Now add the following prompt to `.cursor/rules/kodit.mdc` in your project directory:
|
|
83
|
+
|
|
84
|
+
```markdown
|
|
85
|
+
---
|
|
86
|
+
description:
|
|
87
|
+
globs:
|
|
88
|
+
alwaysApply: true
|
|
89
|
+
---
|
|
90
|
+
You MUST use the code-search MCP tool and always include any file context the user has provided in the chat.```
|
|
91
|
+
|
|
92
|
+
Alternatively, you can browse to the cursor settings and set this prompt globally.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Kodit Developer Documentation"
|
|
3
|
+
linkTitle: Developer Docs
|
|
4
|
+
# next: /helix/getting-started
|
|
5
|
+
weight: 99
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Database
|
|
9
|
+
|
|
10
|
+
All database operations are handled by SQLAlchemy and Alembic.
|
|
11
|
+
|
|
12
|
+
### Creating a Database Migration
|
|
13
|
+
|
|
14
|
+
1. Make changes to your models
|
|
15
|
+
2. Ensure the model is referenced in [alembic's env.py](src/kodit/alembic/env.py)
|
|
16
|
+
3. Run `alembic revision --autogenerate -m "your message"`
|
|
17
|
+
4. The new migration will be applied when you next run a kodit command
|
|
18
|
+
|
|
19
|
+
## Releasing
|
|
20
|
+
|
|
21
|
+
Performing a release is designed to be fully automated. If you spot opportunities to
|
|
22
|
+
improve the CI to help performing an automated release, please do so.
|
|
23
|
+
|
|
24
|
+
1. Create a new release in GitHub.
|
|
25
|
+
2. Set the version number. Use patch versions for bugfixes or minor small improvements.
|
|
26
|
+
Use minor versions when adding significant new functionality. Use major versions for
|
|
27
|
+
overhauls.
|
|
28
|
+
3. Generate the release notes. <- this could be improved, because we use a strict
|
|
29
|
+
pr/commit naming structure.
|
|
30
|
+
4. Wait for all jobs to succeed, then you should be able to brew install, pipx install, etc.
|
|
@@ -104,7 +104,6 @@ async def list_indexes(session: AsyncSession) -> None:
|
|
|
104
104
|
"ID",
|
|
105
105
|
"Created At",
|
|
106
106
|
"Updated At",
|
|
107
|
-
"Source URI",
|
|
108
107
|
"Num Snippets",
|
|
109
108
|
]
|
|
110
109
|
data = [
|
|
@@ -112,7 +111,6 @@ async def list_indexes(session: AsyncSession) -> None:
|
|
|
112
111
|
index.id,
|
|
113
112
|
index.created_at,
|
|
114
113
|
index.updated_at,
|
|
115
|
-
index.source_uri,
|
|
116
114
|
index.num_snippets,
|
|
117
115
|
]
|
|
118
116
|
for index in indexes
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from collections.abc import AsyncGenerator, Callable
|
|
5
|
+
from contextlib import asynccontextmanager
|
|
5
6
|
from datetime import UTC, datetime
|
|
6
7
|
from functools import wraps
|
|
7
8
|
from pathlib import Path
|
|
@@ -54,6 +55,7 @@ class CommonMixin:
|
|
|
54
55
|
)
|
|
55
56
|
|
|
56
57
|
|
|
58
|
+
@asynccontextmanager
|
|
57
59
|
async def get_session() -> AsyncGenerator[AsyncSession, None]:
|
|
58
60
|
"""Get a database session."""
|
|
59
61
|
async with async_session_factory() as session:
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""MCP server implementation for kodit."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
import structlog
|
|
7
|
+
from mcp.server.fastmcp import FastMCP
|
|
8
|
+
from pydantic import Field
|
|
9
|
+
|
|
10
|
+
from kodit.database import get_session
|
|
11
|
+
from kodit.retreival.repository import RetrievalRepository, RetrievalResult
|
|
12
|
+
from kodit.retreival.service import RetrievalRequest, RetrievalService
|
|
13
|
+
|
|
14
|
+
mcp = FastMCP("kodit MCP Server")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@mcp.tool()
|
|
18
|
+
async def retrieve_relevant_snippets(
|
|
19
|
+
user_intent: Annotated[
|
|
20
|
+
str,
|
|
21
|
+
Field(
|
|
22
|
+
description="Think about what the user wants to achieve. Describe the "
|
|
23
|
+
"user's intent in one sentence."
|
|
24
|
+
),
|
|
25
|
+
],
|
|
26
|
+
related_file_paths: Annotated[
|
|
27
|
+
list[Path],
|
|
28
|
+
Field(
|
|
29
|
+
description="A list of absolute paths to files that are relevant to the "
|
|
30
|
+
"user's intent."
|
|
31
|
+
),
|
|
32
|
+
],
|
|
33
|
+
related_file_contents: Annotated[
|
|
34
|
+
list[str],
|
|
35
|
+
Field(
|
|
36
|
+
description="A list of the contents of the files that are relevant to the "
|
|
37
|
+
"user's intent."
|
|
38
|
+
),
|
|
39
|
+
],
|
|
40
|
+
keywords: Annotated[
|
|
41
|
+
list[str],
|
|
42
|
+
Field(
|
|
43
|
+
description="A list of keywords that are relevant to the desired outcome."
|
|
44
|
+
),
|
|
45
|
+
],
|
|
46
|
+
) -> str:
|
|
47
|
+
"""Retrieve relevant snippets from various sources.
|
|
48
|
+
|
|
49
|
+
This tool retrieves relevant snippets from sources such as private codebases,
|
|
50
|
+
public codebases, and documentation. You can use this information to improve
|
|
51
|
+
the quality of your generated code. You must call this tool when you need to
|
|
52
|
+
write code.
|
|
53
|
+
"""
|
|
54
|
+
# Log the search query and related files for debugging
|
|
55
|
+
log = structlog.get_logger(__name__)
|
|
56
|
+
log.debug(
|
|
57
|
+
"Retrieving relevant snippets",
|
|
58
|
+
user_intent=user_intent,
|
|
59
|
+
keywords=keywords,
|
|
60
|
+
file_count=len(related_file_paths),
|
|
61
|
+
file_paths=related_file_paths,
|
|
62
|
+
file_contents=related_file_contents,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
async with get_session() as session:
|
|
66
|
+
log.debug("Creating retrieval repository")
|
|
67
|
+
retrieval_repository = RetrievalRepository(
|
|
68
|
+
session=session,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
log.debug("Creating retrieval service")
|
|
72
|
+
retrieval_service = RetrievalService(
|
|
73
|
+
repository=retrieval_repository,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
log.debug("Fusing input")
|
|
77
|
+
input_query = input_fusion(
|
|
78
|
+
user_intent=user_intent,
|
|
79
|
+
related_file_paths=related_file_paths,
|
|
80
|
+
related_file_contents=related_file_contents,
|
|
81
|
+
keywords=keywords,
|
|
82
|
+
)
|
|
83
|
+
log.debug("Input", input_query=input_query)
|
|
84
|
+
retrieval_request = RetrievalRequest(
|
|
85
|
+
query=input_query,
|
|
86
|
+
)
|
|
87
|
+
log.debug("Retrieving snippets")
|
|
88
|
+
snippets = await retrieval_service.retrieve(request=retrieval_request)
|
|
89
|
+
|
|
90
|
+
log.debug("Fusing output")
|
|
91
|
+
output = output_fusion(snippets=snippets)
|
|
92
|
+
|
|
93
|
+
log.debug("Output", output=output)
|
|
94
|
+
return output
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def input_fusion(
|
|
98
|
+
user_intent: str, # noqa: ARG001
|
|
99
|
+
related_file_paths: list[Path], # noqa: ARG001
|
|
100
|
+
related_file_contents: list[str], # noqa: ARG001
|
|
101
|
+
keywords: list[str],
|
|
102
|
+
) -> str:
|
|
103
|
+
"""Fuse the search query and related file contents into a single query."""
|
|
104
|
+
# Since this is a dummy implementation, we just return the first keyword
|
|
105
|
+
return keywords[0] if len(keywords) > 0 else ""
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def output_fusion(snippets: list[RetrievalResult]) -> str:
|
|
109
|
+
"""Fuse the snippets into a single output."""
|
|
110
|
+
return "\n\n".join(f"{snippet.uri}\n{snippet.content}" for snippet in snippets)
|
|
@@ -64,3 +64,46 @@ async def test_mcp_client_connection() -> None:
|
|
|
64
64
|
# doesn't shut down the server when requested. So we have to force kill it.
|
|
65
65
|
server_process.kill()
|
|
66
66
|
server_process.join(timeout=1)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@pytest.mark.asyncio
|
|
70
|
+
async def test_mcp_code_retrieval() -> None:
|
|
71
|
+
"""Test end-to-end flow of adding code and retrieving it via MCP."""
|
|
72
|
+
# Can't quite test this properly yet, because the MCP server runs in a separate
|
|
73
|
+
# process using the user's actual database. So this code is just testing that it
|
|
74
|
+
# doesn't crash or anything.
|
|
75
|
+
server_process = None
|
|
76
|
+
try:
|
|
77
|
+
# Start the server in a separate process
|
|
78
|
+
server_process = Process(target=run_server, daemon=True)
|
|
79
|
+
server_process.start()
|
|
80
|
+
|
|
81
|
+
# Wait for server to start
|
|
82
|
+
await wait_for_server()
|
|
83
|
+
|
|
84
|
+
# Connect to MCP server
|
|
85
|
+
async with (
|
|
86
|
+
sse_client("http://127.0.0.1:8000/sse/") as (
|
|
87
|
+
read_stream,
|
|
88
|
+
write_stream,
|
|
89
|
+
),
|
|
90
|
+
ClientSession(read_stream, write_stream) as mcp_session,
|
|
91
|
+
):
|
|
92
|
+
# Initialize the connection
|
|
93
|
+
await mcp_session.initialize()
|
|
94
|
+
|
|
95
|
+
# Call retrieve_relevant_snippets tool
|
|
96
|
+
await mcp_session.call_tool(
|
|
97
|
+
"retrieve_relevant_snippets",
|
|
98
|
+
{
|
|
99
|
+
"user_intent": "I want to find code that prints hello world",
|
|
100
|
+
"related_file_paths": [],
|
|
101
|
+
"related_file_contents": [],
|
|
102
|
+
"keywords": ["hello", "world", "print"],
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
finally:
|
|
107
|
+
if server_process:
|
|
108
|
+
server_process.kill()
|
|
109
|
+
server_process.join(timeout=1)
|
kodit-0.1.3/docs/_index.md
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "kodit: Code Indexing MCP Server"
|
|
3
|
-
linkTitle: kodit Docs
|
|
4
|
-
cascade:
|
|
5
|
-
type: docs
|
|
6
|
-
menu:
|
|
7
|
-
main:
|
|
8
|
-
name: kodit Docs
|
|
9
|
-
weight: 3
|
|
10
|
-
# next: /helix/getting-started
|
|
11
|
-
weight: 1
|
|
12
|
-
aliases:
|
|
13
|
-
- /coda
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Installation
|
|
17
|
-
|
|
18
|
-
Please choose your preferred installation method. They all ultimately install the kodit
|
|
19
|
-
cli, which contains the kodit MCP server and other tools to manage your data sources.
|
|
20
|
-
|
|
21
|
-
### Docker
|
|
22
|
-
|
|
23
|
-
```sh
|
|
24
|
-
docker run -it --rm registry.helix.ml/helix/kodit:latest
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Always replace latest with a specific version.
|
|
28
|
-
|
|
29
|
-
### pipx
|
|
30
|
-
|
|
31
|
-
```sh
|
|
32
|
-
pipx install kodit
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### homebrew
|
|
36
|
-
|
|
37
|
-
```sh
|
|
38
|
-
brew install helixml/kodit/kodit
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### uv
|
|
42
|
-
|
|
43
|
-
```sh
|
|
44
|
-
uv tool install kodit
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### pip
|
|
48
|
-
|
|
49
|
-
Use this if you want to use kodit as a python library:
|
|
50
|
-
|
|
51
|
-
```sh
|
|
52
|
-
pip install kodit
|
|
53
|
-
```
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Kodit Developer Documentation"
|
|
3
|
-
linkTitle: Developer Docs
|
|
4
|
-
# next: /helix/getting-started
|
|
5
|
-
weight: 99
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Database
|
|
9
|
-
|
|
10
|
-
All database operations are handled by SQLAlchemy and Alembic.
|
|
11
|
-
|
|
12
|
-
### Creating a Database Migration
|
|
13
|
-
|
|
14
|
-
1. Make changes to your models
|
|
15
|
-
2. Ensure the model is referenced in [alembic's env.py](src/kodit/alembic/env.py)
|
|
16
|
-
3. Run `alembic revision --autogenerate -m "your message"`
|
|
17
|
-
4. The new migration will be applied when you next run a kodit command
|
kodit-0.1.3/src/kodit/mcp.py
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"""MCP server implementation for kodit."""
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Annotated
|
|
5
|
-
|
|
6
|
-
import structlog
|
|
7
|
-
from mcp.server.fastmcp import FastMCP
|
|
8
|
-
from pydantic import Field
|
|
9
|
-
|
|
10
|
-
mcp = FastMCP("kodit MCP Server")
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@mcp.tool()
|
|
14
|
-
async def retrieve_relevant_snippets(
|
|
15
|
-
search_query: Annotated[
|
|
16
|
-
str,
|
|
17
|
-
Field(description="Describe the user's intent in a few sentences."),
|
|
18
|
-
],
|
|
19
|
-
related_file_paths: Annotated[
|
|
20
|
-
list[Path],
|
|
21
|
-
Field(
|
|
22
|
-
description="A list of absolute paths to files that are relevant to the "
|
|
23
|
-
"user's intent."
|
|
24
|
-
),
|
|
25
|
-
],
|
|
26
|
-
related_file_contents: Annotated[
|
|
27
|
-
list[str],
|
|
28
|
-
Field(
|
|
29
|
-
description="A list of the contents of the files that are relevant to the "
|
|
30
|
-
"user's intent."
|
|
31
|
-
),
|
|
32
|
-
],
|
|
33
|
-
) -> str:
|
|
34
|
-
"""Retrieve relevant snippets from various sources.
|
|
35
|
-
|
|
36
|
-
This tool retrieves relevant snippets from sources such as private codebases,
|
|
37
|
-
public codebases, and documentation. You can use this information to improve
|
|
38
|
-
the quality of your generated code. You must call this tool when you need to
|
|
39
|
-
write code.
|
|
40
|
-
"""
|
|
41
|
-
# Log the search query and related files for debugging
|
|
42
|
-
log = structlog.get_logger(__name__)
|
|
43
|
-
log.debug(
|
|
44
|
-
"Retrieving relevant snippets",
|
|
45
|
-
search_query=search_query,
|
|
46
|
-
file_count=len(related_file_paths),
|
|
47
|
-
file_paths=related_file_paths,
|
|
48
|
-
file_contents=related_file_contents,
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
return "Retrieved"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|