Skip to content

Commit 9362b38

Browse files
authored
Feature/new cmd analyze (#55)
* Duplicate changelog as analyze * cli to Analyze
1 parent f67449f commit 9362b38

6 files changed

Lines changed: 160 additions & 0 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,18 @@ cocode github sync-labels pipelex/cocode ./labels.json --delete-extra
124124

125125
### Commands for Other Features
126126

127+
#### Code Analysis
128+
```bash
129+
# Analyze git diff with a specific prompt/query
130+
cocode analyze diff v1.0.0 --prompt "What are the main architectural changes in this update?"
131+
132+
# Analyze security-related changes
133+
cocode analyze diff HEAD~10 --prompt "Identify any security vulnerabilities or improvements"
134+
135+
# Analyze performance impacts
136+
cocode analyze diff main --prompt "What changes might affect application performance?"
137+
```
138+
127139
## ⚠️ Limitations
128140

129141
This tool is in early development! There are many things to fix and improve. You may encounter bugs, incomplete features, or unexpected behavior. We're actively working on making Cocode more robust and user-friendly.

cocode/cli/analyze/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Analyze management module."""

cocode/cli/analyze/analyze_cli.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""
2+
Analyze management CLI commands.
3+
"""
4+
5+
import asyncio
6+
from typing import Annotated, List, Optional
7+
8+
import typer
9+
from pipelex.core.pipes.pipe_run_params import PipeRunMode
10+
from pipelex.hub import get_pipeline_tracker
11+
12+
from cocode.common import get_output_dir, validate_repo_path
13+
from cocode.swe.swe_cmd import swe_from_repo_diff_with_prompt
14+
15+
analyze_app = typer.Typer(
16+
name="analyze",
17+
help="Analyze management and generation commands",
18+
add_completion=False,
19+
rich_markup_mode="rich",
20+
no_args_is_help=True,
21+
)
22+
23+
24+
@analyze_app.command("diff")
25+
def analyze_diff_cmd(
26+
prompt: Annotated[
27+
str,
28+
typer.Option("--prompt", "-p", help="Prompt to analyze the git diff"),
29+
],
30+
version: Annotated[
31+
str,
32+
typer.Argument(help="Git version/tag/commit to compare current version against"),
33+
],
34+
repo_path: Annotated[
35+
str,
36+
typer.Argument(help="Repository path (local directory) or GitHub URL/identifier (owner/repo or https://github.com/owner/repo)"),
37+
] = ".",
38+
output_dir: Annotated[
39+
Optional[str],
40+
typer.Option("--output-dir", "-o", help="Output directory path. Use 'stdout' to print to console. Defaults to config value if not provided"),
41+
] = None,
42+
output_filename: Annotated[
43+
str,
44+
typer.Option("--output-filename", "-n", help="Output filename"),
45+
] = "analyze-diff.md",
46+
dry_run: Annotated[
47+
bool,
48+
typer.Option("--dry", help="Run pipeline in dry mode (no actual execution)"),
49+
] = False,
50+
ignore_patterns: Annotated[
51+
Optional[List[str]],
52+
typer.Option(
53+
"--ignore-pattern", "-i", help="Patterns to exclude from git diff (e.g., '*.log', 'temp/', 'build/'). Can be specified multiple times."
54+
),
55+
] = None,
56+
) -> None:
57+
"""Generate analyze from git diff comparing current version to specified version. Supports both local repositories and GitHub repositories."""
58+
repo_path = validate_repo_path(repo_path)
59+
output_dir = get_output_dir(output_dir)
60+
to_stdout = output_dir == "stdout"
61+
pipe_run_mode = PipeRunMode.DRY if dry_run else PipeRunMode.LIVE
62+
63+
asyncio.run(
64+
swe_from_repo_diff_with_prompt(
65+
pipe_code="analyze_git_diff",
66+
prompt=prompt,
67+
repo_path=repo_path,
68+
version=version,
69+
output_filename=output_filename,
70+
output_dir=output_dir,
71+
to_stdout=to_stdout,
72+
pipe_run_mode=pipe_run_mode,
73+
ignore_patterns=ignore_patterns,
74+
)
75+
)
76+
get_pipeline_tracker().output_flowchart()

cocode/cli/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from typing_extensions import override
1313

1414
from cocode.cli.ai_instructions.ai_instructions_cli import ai_instructions_app
15+
from cocode.cli.analyze.analyze_cli import analyze_app
1516
from cocode.cli.changelog.changelog_cli import changelog_app
1617
from cocode.cli.doc.doc_cli import doc_app
1718
from cocode.cli.features.features_cli import features_app
@@ -50,6 +51,7 @@ def get_command(self, ctx: Context, cmd_name: str) -> Optional[Command]:
5051

5152
# Add command groups
5253
app.add_typer(doc_app, name="doc", help="Documentation management and automation commands")
54+
app.add_typer(analyze_app, name="analyze", help="Analyze generation and management commands")
5355
app.add_typer(changelog_app, name="changelog", help="Changelog generation and management commands")
5456
app.add_typer(ai_instructions_app, name="ai_instructions", help="AI instructions update and management commands")
5557
app.add_typer(repo_app, name="repo", help="Repository analysis and processing commands")

cocode/pipelex_libraries/pipelines/swe_diff/swe_diff.plx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ Be sure to include changes to code but also complementary pipelines, scripts, do
8787
@git_diff
8888
"""
8989

90+
[pipe.analyze_git_diff]
91+
type = "PipeLLM"
92+
definition = "Analyze the git diff based on a prompt."
93+
inputs = { git_diff = "GitDiff", prompt = "Text" }
94+
output = "Text"
95+
llm = "llm_for_large_text"
96+
system_prompt = """
97+
You are an expert technical writer and software architect. Your task is to carefully review and analyze the code diff.
98+
"""
99+
prompt_template = """
100+
Analyze the following code diff based on this prompt: $prompt
101+
102+
@git_diff
103+
104+
Answer in markdown format.
105+
"""
106+
90107
[pipe.format_changelog_as_markdown]
91108
type = "PipeJinja2"
92109
definition = "Format the final changelog in markdown with proper structure"

cocode/swe/swe_cmd.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
from cocode.utils import NoDifferencesFound, run_git_diff_command
2121

2222

23+
class SweFromRepoDiffWithPromptError(Exception):
24+
pass
25+
26+
2327
async def swe_from_repo(
2428
pipe_code: str,
2529
repo_path: str,
@@ -145,6 +149,54 @@ async def swe_from_repo_diff(
145149
)
146150

147151

152+
async def swe_from_repo_diff_with_prompt(
153+
pipe_code: str,
154+
prompt: str,
155+
repo_path: str,
156+
version: str,
157+
output_filename: str,
158+
output_dir: str,
159+
to_stdout: bool,
160+
pipe_run_mode: PipeRunMode,
161+
ignore_patterns: Optional[List[str]] = None,
162+
) -> None:
163+
"""Process SWE analysis from a git diff comparing current version to specified version."""
164+
log.info(f"Processing SWE from git diff: comparing current to '{version}' in '{repo_path}'")
165+
166+
if not prompt:
167+
raise SweFromRepoDiffWithPromptError("Prompt is required")
168+
169+
# Generate git diff
170+
try:
171+
git_diff = run_git_diff_command(repo_path=repo_path, version=version, ignore_patterns=ignore_patterns)
172+
except NoDifferencesFound as exc:
173+
log.info(f"Aborting: {exc}")
174+
return
175+
176+
# Run the pipe
177+
pipe_output = await execute_pipeline(
178+
pipe_code=pipe_code,
179+
pipe_run_mode=pipe_run_mode,
180+
input_memory={
181+
"git_diff": {
182+
"concept": "swe_diff.GitDiff",
183+
"content": git_diff,
184+
},
185+
"prompt": prompt,
186+
},
187+
)
188+
189+
get_report_delegate().generate_report()
190+
191+
# Process through SWE pipeline and handle output
192+
await process_swe_pipeline_result(
193+
pipe_output=pipe_output,
194+
output_filename=output_filename,
195+
output_dir=output_dir,
196+
to_stdout=to_stdout,
197+
)
198+
199+
148200
async def swe_doc_update_from_diff(
149201
repo_path: str,
150202
version: str,

0 commit comments

Comments
 (0)