Skip to content

Commit 0a62cd9

Browse files
authored
Merge pull request #555 from Cloud-Code-AI/549-kaizen-cli-make-easy-setup-with-ollama
549 kaizen cli make easy setup with ollama
2 parents 6e3d8a8 + 3c893a3 commit 0a62cd9

12 files changed

+242
-108
lines changed

cli/kaizen_cli/cli.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .commands.config_commands import config
44
from .commands.unit_test_commands import unit_test
55
from .commands.reviewer_commands import reviewer
6+
from .hooks.setup import hooks
67
from kaizen.generator.e2e_tests import E2ETestGenerator
78

89

@@ -23,6 +24,7 @@ def ui_tests(url):
2324
cli.add_command(config)
2425
cli.add_command(unit_test)
2526
cli.add_command(reviewer)
27+
cli.add_command(hooks)
2628

2729
if __name__ == "__main__":
2830
cli()

cli/kaizen_cli/config/default_config.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@
44
"models": [
55
{
66
"model_name": "default",
7-
"litellm_params": {
8-
"model": "azure/gpt-4o-mini",
9-
"api_key": "os.environ/AZURE_API_KEY",
10-
"api_base": "os.environ/AZURE_API_BASE",
11-
},
7+
"litellm_params": {"model": "ollama/phi3"},
128
},
139
]
1410
},
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh
2+
# hooks/prepare-commit-msg
3+
4+
# Run your CLI command and capture the output
5+
commit_msg=$(kaizen-cli generate-commit-msg)
6+
7+
# Overwrite the commit message file with the generated message
8+
echo "$commit_msg" > "$1"

cli/kaizen_cli/hooks/setup.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import os
2+
import shutil
3+
import click
4+
5+
HOOK_TYPES = ["prepare-commit-msg"]
6+
7+
8+
@click.group()
9+
def hooks():
10+
"""Manage git hooks"""
11+
pass
12+
13+
14+
@hooks.command()
15+
@click.argument("hook_type", type=click.Choice(HOOK_TYPES))
16+
def install(hook_type):
17+
"""Install a specific git hook"""
18+
source = os.path.join(os.path.dirname(__file__), "hooks", hook_type)
19+
destination = os.path.join(".git", "hooks", hook_type)
20+
21+
if not os.path.exists(source):
22+
click.echo(f"Error: Hook script for {hook_type} not found.")
23+
return
24+
25+
try:
26+
shutil.copy(source, destination)
27+
os.chmod(destination, 0o755)
28+
click.echo(f"{hook_type} hook installed successfully")
29+
except IOError as e:
30+
click.echo(f"Error installing {hook_type} hook: {str(e)}")
31+
32+
33+
@hooks.command()
34+
def install_all():
35+
"""Install all available git hooks"""
36+
for hook_type in HOOK_TYPES:
37+
ctx = click.get_current_context()
38+
ctx.invoke(install, hook_type=hook_type)
39+
40+
41+
@hooks.command()
42+
@click.argument("hook_type", type=click.Choice(HOOK_TYPES))
43+
def uninstall(hook_type):
44+
"""Uninstall a specific git hook"""
45+
hook_path = os.path.join(".git", "hooks", hook_type)
46+
if os.path.exists(hook_path):
47+
os.remove(hook_path)
48+
click.echo(f"{hook_type} hook uninstalled successfully")
49+
else:
50+
click.echo(f"{hook_type} hook not found")
51+
52+
53+
@hooks.command()
54+
def uninstall_all():
55+
"""Uninstall all git hooks"""
56+
for hook_type in HOOK_TYPES:
57+
ctx = click.get_current_context()
58+
ctx.invoke(uninstall, hook_type=hook_type)

cli/poetry.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ readme = "README.md"
88
[tool.poetry.dependencies]
99
python = "^3.9.0"
1010
click = "^8.1.3"
11-
kaizen-cloudcode = "^0.4.11"
11+
kaizen-cloudcode = "^0.4.12"
1212

1313
[tool.poetry.group.dev.dependencies]
1414
kaizen-cloudcode = {path = "..", develop = true, optional = true}

kaizen/retriever/code_chunker.py

+84-16
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,100 @@
77
def chunk_code(code: str, language: str) -> ParsedBody:
88
parser = ParserFactory.get_parser(language)
99
tree = parser.parse(code.encode("utf8"))
10-
10+
code_bytes = code.encode("utf8")
1111
body: ParsedBody = {
12+
"imports": [],
13+
"global_variables": [],
14+
"type_definitions": [],
1215
"functions": {},
16+
"async_functions": {},
1317
"classes": {},
1418
"hooks": {},
1519
"components": {},
20+
"jsx_elements": [],
1621
"other_blocks": [],
1722
}
18-
# code_bytes = code.encode("utf8")
1923

2024
def process_node(node):
21-
result = parse_code(code, language)
25+
result = parse_code(node, code_bytes)
2226
if result:
23-
# Assuming parse_code is modified to return line numbers
2427
start_line = result.get("start_line", 0)
2528
end_line = result.get("end_line", 0)
2629

27-
if result["type"] == "function":
30+
if result["type"] == "import_statement":
31+
body["imports"].append(
32+
{
33+
"code": result["code"],
34+
"start_line": start_line,
35+
"end_line": end_line,
36+
}
37+
)
38+
elif (
39+
result["type"] == "variable_declaration"
40+
and node.parent.type == "program"
41+
):
42+
body["global_variables"].append(
43+
{
44+
"code": result["code"],
45+
"start_line": start_line,
46+
"end_line": end_line,
47+
}
48+
)
49+
elif result["type"] in ["type_alias", "interface_declaration"]:
50+
body["type_definitions"].append(
51+
{
52+
"name": result["name"],
53+
"code": result["code"],
54+
"start_line": start_line,
55+
"end_line": end_line,
56+
}
57+
)
58+
elif result["type"] == "function":
2859
if is_react_hook(result["name"]):
2960
body["hooks"][result["name"]] = {
3061
"code": result["code"],
3162
"start_line": start_line,
3263
"end_line": end_line,
3364
}
3465
elif is_react_component(result["code"]):
35-
body["components"][result["name"]] = result["code"]
66+
body["components"][result["name"]] = {
67+
"code": result["code"],
68+
"start_line": start_line,
69+
"end_line": end_line,
70+
}
71+
elif "async" in result["code"].split()[0]:
72+
body["async_functions"][result["name"]] = {
73+
"code": result["code"],
74+
"start_line": start_line,
75+
"end_line": end_line,
76+
}
3677
else:
37-
body["functions"][result["name"]] = result["code"]
78+
body["functions"][result["name"]] = {
79+
"code": result["code"],
80+
"start_line": start_line,
81+
"end_line": end_line,
82+
}
3883
elif result["type"] == "class":
3984
if is_react_component(result["code"]):
40-
body["components"][result["name"]] = result["code"]
85+
body["components"][result["name"]] = {
86+
"code": result["code"],
87+
"start_line": start_line,
88+
"end_line": end_line,
89+
}
4190
else:
42-
body["classes"][result["name"]] = result["code"]
43-
elif result["type"] == "component":
44-
body["components"][result["name"]] = result["code"]
45-
elif result["type"] == "impl":
46-
body["classes"][result["name"]] = result["code"]
91+
body["classes"][result["name"]] = {
92+
"code": result["code"],
93+
"start_line": start_line,
94+
"end_line": end_line,
95+
}
96+
elif result["type"] == "jsx_element":
97+
body["jsx_elements"].append(
98+
{
99+
"code": result["code"],
100+
"start_line": start_line,
101+
"end_line": end_line,
102+
}
103+
)
47104
else:
48105
for child in node.children:
49106
process_node(child)
@@ -55,8 +112,14 @@ def process_node(node):
55112
for section in body.values():
56113
if isinstance(section, dict):
57114
for code_block in section.values():
58-
start = code.index(code_block)
59-
collected_ranges.append((start, start + len(code_block)))
115+
collected_ranges.append(
116+
(code_block["start_line"], code_block["end_line"])
117+
)
118+
elif isinstance(section, list):
119+
for code_block in section:
120+
collected_ranges.append(
121+
(code_block["start_line"], code_block["end_line"])
122+
)
60123

61124
collected_ranges.sort()
62125
last_end = 0
@@ -76,5 +139,10 @@ def is_react_hook(name: str) -> bool:
76139

77140
def is_react_component(code: str) -> bool:
78141
return (
79-
"React" in code or "jsx" in code.lower() or "tsx" in code.lower() or "<" in code
142+
"React" in code
143+
or "jsx" in code.lower()
144+
or "tsx" in code.lower()
145+
or "<" in code
146+
or "props" in code
147+
or "render" in code
80148
)

0 commit comments

Comments
 (0)