centicodehelp 0.2.0__py3-none-any.whl
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.
- centicodehelp/__init__.py +3 -0
- centicodehelp/ai/llm_client.py +150 -0
- centicodehelp/ai/prompts.py +63 -0
- centicodehelp/ai/providers.py +195 -0
- centicodehelp/ai/reviewer.py +139 -0
- centicodehelp/analysis/binary_analyzer.py +124 -0
- centicodehelp/analysis/detector.py +80 -0
- centicodehelp/analysis/parser.py +41 -0
- centicodehelp/analysis/static_analyzer.py +194 -0
- centicodehelp/cli/banner.py +60 -0
- centicodehelp/cli/commands/ai.py +128 -0
- centicodehelp/cli/commands/analyze.py +389 -0
- centicodehelp/cli/commands/check.py +91 -0
- centicodehelp/cli/commands/config.py +67 -0
- centicodehelp/cli/commands/fix.py +170 -0
- centicodehelp/cli/commands/providers.py +81 -0
- centicodehelp/cli/commands/scan.py +129 -0
- centicodehelp/cli/commands/setup.py +93 -0
- centicodehelp/cli/commands/update.py +51 -0
- centicodehelp/cli/main.py +141 -0
- centicodehelp/cli/theme.py +50 -0
- centicodehelp/core/config.py +58 -0
- centicodehelp/core/models.py +31 -0
- centicodehelp/fixer/applier.py +23 -0
- centicodehelp/fixer/patcher.py +42 -0
- centicodehelp-0.2.0.dist-info/METADATA +79 -0
- centicodehelp-0.2.0.dist-info/RECORD +30 -0
- centicodehelp-0.2.0.dist-info/WHEEL +5 -0
- centicodehelp-0.2.0.dist-info/entry_points.txt +4 -0
- centicodehelp-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Theme, color palette and brand assets for centicodehelp."""
|
|
2
|
+
|
|
3
|
+
from rich.theme import Theme
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
|
|
6
|
+
# Centi09 brand color palette (centi09.de)
|
|
7
|
+
COLOR_PURPLE = "#C084FC" # Primary purple
|
|
8
|
+
COLOR_BLUE = "#38BDF8" # Secondary cyan/blue
|
|
9
|
+
COLOR_INDIGO = "#818CF8" # Accent indigo
|
|
10
|
+
COLOR_DARK_BG = "#0a0a0f" # Deep dark
|
|
11
|
+
COLOR_TEXT = "#e0e0e0" # Light gray text
|
|
12
|
+
COLOR_CRITICAL = "bold #ef4444" # Critical red
|
|
13
|
+
COLOR_HIGH = "#fb923c" # High orange
|
|
14
|
+
COLOR_MEDIUM = "#facc15" # Medium yellow
|
|
15
|
+
COLOR_LOW = "#60a5fa" # Low sky blue
|
|
16
|
+
COLOR_INFO = "#94a3b8" # Info slate
|
|
17
|
+
COLOR_SUCCESS = "#4ade80" # Green success
|
|
18
|
+
COLOR_ERROR = "#f87171" # Red error
|
|
19
|
+
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
CUSTOM_THEME = Theme({
|
|
23
|
+
"brand.primary": COLOR_PURPLE,
|
|
24
|
+
"brand.secondary": COLOR_BLUE,
|
|
25
|
+
"brand.accent": COLOR_INDIGO,
|
|
26
|
+
"brand.text": COLOR_TEXT,
|
|
27
|
+
"severity.critical": COLOR_CRITICAL,
|
|
28
|
+
"severity.high": COLOR_HIGH,
|
|
29
|
+
"severity.medium": COLOR_MEDIUM,
|
|
30
|
+
"severity.low": COLOR_LOW,
|
|
31
|
+
"severity.info": COLOR_INFO,
|
|
32
|
+
"status.success": COLOR_SUCCESS,
|
|
33
|
+
"status.error": COLOR_ERROR,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
# Reconfigure stdout/stderr to UTF-8 on Windows
|
|
37
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
38
|
+
try:
|
|
39
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
42
|
+
if hasattr(sys.stderr, "reconfigure"):
|
|
43
|
+
try:
|
|
44
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
45
|
+
except Exception:
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
console = Console(theme=CUSTOM_THEME, legacy_windows=False)
|
|
49
|
+
|
|
50
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
import yaml
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
# Primary config location: C:\centicodehelps\config\centicodehelp.yaml
|
|
8
|
+
PRIMARY_CONFIG_PATH = Path("C:/centicodehelps/config/centicodehelp.yaml")
|
|
9
|
+
LEGACY_CONFIG_DIR = Path.home() / ".centicodehelp"
|
|
10
|
+
LEGACY_CONFIG_PATH = LEGACY_CONFIG_DIR / "config.yaml"
|
|
11
|
+
OLD_centicodehelp_CONFIG = Path.home() / ".centicodehelp" / "config.yaml"
|
|
12
|
+
|
|
13
|
+
class CentiCodeHelpConfig(BaseModel):
|
|
14
|
+
default_provider: str = Field(default="ollama", description="Default LLM provider")
|
|
15
|
+
default_model: str = Field(default="qwen2.5-coder:7b", description="Default LLM model name")
|
|
16
|
+
api_keys: Dict[str, str] = Field(default_factory=dict, description="Provider API keys")
|
|
17
|
+
api_bases: Dict[str, str] = Field(default_factory=dict, description="Custom base URLs (e.g. for Ollama or LocalAI)")
|
|
18
|
+
ollama_base_url: str = Field(default="http://localhost:11434", description="Ollama API URL")
|
|
19
|
+
auto_backup: bool = Field(default=True, description="Create backups before applying patches")
|
|
20
|
+
|
|
21
|
+
# Alias for backwards compatibility
|
|
22
|
+
centicodehelpConfig = CentiCodeHelpConfig
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_config_path() -> Path:
|
|
26
|
+
env_path = os.getenv("CENTICODEHELP_CONFIG") or os.getenv("centicodehelp_CONFIG")
|
|
27
|
+
if env_path:
|
|
28
|
+
return Path(env_path)
|
|
29
|
+
if PRIMARY_CONFIG_PATH.exists():
|
|
30
|
+
return PRIMARY_CONFIG_PATH
|
|
31
|
+
if PRIMARY_CONFIG_PATH.parent.exists():
|
|
32
|
+
return PRIMARY_CONFIG_PATH
|
|
33
|
+
if LEGACY_CONFIG_PATH.exists():
|
|
34
|
+
return LEGACY_CONFIG_PATH
|
|
35
|
+
if OLD_centicodehelp_CONFIG.exists():
|
|
36
|
+
return OLD_centicodehelp_CONFIG
|
|
37
|
+
return PRIMARY_CONFIG_PATH
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def load_config() -> CentiCodeHelpConfig:
|
|
41
|
+
config_path = get_config_path()
|
|
42
|
+
if not config_path.exists():
|
|
43
|
+
return CentiCodeHelpConfig()
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
with open(config_path, "r", encoding="utf-8") as f:
|
|
47
|
+
data = yaml.safe_load(f) or {}
|
|
48
|
+
return CentiCodeHelpConfig(**data)
|
|
49
|
+
except Exception:
|
|
50
|
+
return CentiCodeHelpConfig()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def save_config(config: CentiCodeHelpConfig) -> None:
|
|
54
|
+
config_path = get_config_path()
|
|
55
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
56
|
+
with open(config_path, "w", encoding="utf-8") as f:
|
|
57
|
+
yaml.safe_dump(config.model_dump(), f, default_flow_style=False, sort_keys=False)
|
|
58
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Optional, List, Dict, Any
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
class Severity(str, Enum):
|
|
6
|
+
INFO = "INFO"
|
|
7
|
+
LOW = "LOW"
|
|
8
|
+
MEDIUM = "MEDIUM"
|
|
9
|
+
HIGH = "HIGH"
|
|
10
|
+
CRITICAL = "CRITICAL"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Finding(BaseModel):
|
|
14
|
+
file_path: str
|
|
15
|
+
line: Optional[int] = None
|
|
16
|
+
column: Optional[int] = None
|
|
17
|
+
end_line: Optional[int] = None
|
|
18
|
+
rule_id: str
|
|
19
|
+
severity: Severity = Severity.MEDIUM
|
|
20
|
+
description: str
|
|
21
|
+
code_snippet: Optional[str] = None
|
|
22
|
+
suggested_fix: Optional[str] = None
|
|
23
|
+
language: Optional[str] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AnalysisResult(BaseModel):
|
|
27
|
+
target: str
|
|
28
|
+
findings: List[Finding] = Field(default_factory=list)
|
|
29
|
+
stats: Dict[str, Any] = Field(default_factory=dict)
|
|
30
|
+
fixed: bool = False
|
|
31
|
+
diff: Optional[str] = None
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
class PatchApplier:
|
|
6
|
+
"""Safely applies modified code with automatic backups."""
|
|
7
|
+
|
|
8
|
+
def __init__(self, backup: bool = True):
|
|
9
|
+
self.backup = backup
|
|
10
|
+
|
|
11
|
+
def apply_fix(self, file_path: Path, fixed_content: str) -> bool:
|
|
12
|
+
if not file_path.exists():
|
|
13
|
+
return False
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
if self.backup:
|
|
17
|
+
backup_path = file_path.with_suffix(file_path.suffix + ".bak")
|
|
18
|
+
shutil.copy2(file_path, backup_path)
|
|
19
|
+
|
|
20
|
+
file_path.write_text(fixed_content, encoding="utf-8")
|
|
21
|
+
return True
|
|
22
|
+
except Exception:
|
|
23
|
+
return False
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import difflib
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
class PatchGenerator:
|
|
6
|
+
"""Generates unified diffs between original and modified code."""
|
|
7
|
+
|
|
8
|
+
@staticmethod
|
|
9
|
+
def generate_diff(original_text: str, modified_text: str, file_path: str = "file") -> str:
|
|
10
|
+
original_lines = original_text.splitlines(keepends=True)
|
|
11
|
+
modified_lines = modified_text.splitlines(keepends=True)
|
|
12
|
+
|
|
13
|
+
diff = difflib.unified_diff(
|
|
14
|
+
original_lines,
|
|
15
|
+
modified_lines,
|
|
16
|
+
fromfile=f"a/{file_path}",
|
|
17
|
+
tofile=f"b/{file_path}",
|
|
18
|
+
lineterm=""
|
|
19
|
+
)
|
|
20
|
+
return "".join(diff)
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def extract_code_from_markdown(llm_output: str) -> str:
|
|
24
|
+
"""Extract pure code block from LLM markdown response."""
|
|
25
|
+
lines = llm_output.splitlines()
|
|
26
|
+
code_lines = []
|
|
27
|
+
inside_code_block = False
|
|
28
|
+
|
|
29
|
+
for line in lines:
|
|
30
|
+
if line.strip().startswith("```"):
|
|
31
|
+
if inside_code_block:
|
|
32
|
+
inside_code_block = False
|
|
33
|
+
break
|
|
34
|
+
else:
|
|
35
|
+
inside_code_block = True
|
|
36
|
+
continue
|
|
37
|
+
if inside_code_block:
|
|
38
|
+
code_lines.append(line)
|
|
39
|
+
|
|
40
|
+
if code_lines:
|
|
41
|
+
return "\n".join(code_lines)
|
|
42
|
+
return llm_output.strip()
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: centicodehelp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Dein Code. Besser. Sauber. Cross-platform static and AI-assisted code & binary analysis and auto-fixing tool
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: click>=8.1.0
|
|
8
|
+
Requires-Dist: rich>=13.0.0
|
|
9
|
+
Requires-Dist: litellm>=1.40.0
|
|
10
|
+
Requires-Dist: tree-sitter>=0.23.0
|
|
11
|
+
Requires-Dist: tree-sitter-python>=0.23.0
|
|
12
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
13
|
+
Requires-Dist: pydantic>=2.0.0
|
|
14
|
+
Requires-Dist: fastmcp>=0.1.0
|
|
15
|
+
|
|
16
|
+
# CentiCodeHelp – Mach deinen Code besser.
|
|
17
|
+
|
|
18
|
+
> **Dein Code. Besser. Sauber.**
|
|
19
|
+
> Automatische Sicherheitsanalyse, Qualitätsprüfung und KI-gestützte Code-Reparatur.
|
|
20
|
+
> *Version v0.2.0 • centi09.de*
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## ⚡ Schnellstart
|
|
25
|
+
|
|
26
|
+
CentiCodeHelp bietet kinderleichte Befehle:
|
|
27
|
+
|
|
28
|
+
- **Hauptbefehl**: `centicodehelp`
|
|
29
|
+
- **Kurz-Aliase**: `cch` und `ct`
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# 1. Schnelle statische Analyse (ohne KI)
|
|
33
|
+
cch scan
|
|
34
|
+
|
|
35
|
+
# 2. Vollautomatische Reparatur mit KI & automatischem .bak-Backup
|
|
36
|
+
cch fix samples/vulnerable_code.py
|
|
37
|
+
|
|
38
|
+
# 3. Schnellcheck einer einzelnen Datei
|
|
39
|
+
cch check samples/vulnerable_code.py
|
|
40
|
+
|
|
41
|
+
# 4. Reine KI-Analyse
|
|
42
|
+
cch ai samples/vulnerable_code.py
|
|
43
|
+
|
|
44
|
+
# 5. Interaktiver Einrichtungs-Assistent
|
|
45
|
+
cch setup
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 📂 Neue Projekt- und Workspace-Struktur
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
C:\CentiTools\
|
|
54
|
+
├── centicodehelp\ # Code-Analyse, KI-Audit, Auto-Fixing und CLI
|
|
55
|
+
├── config\ # Gemeinsame Konfigurationen (centicodehelp.yaml)
|
|
56
|
+
└── samples\ # Gemeinsame Testdateien (Python, JS, Java, C++)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🤖 MCP-Server & Antigravity-Integration
|
|
62
|
+
|
|
63
|
+
CentiCodeHelp beinhaltet einen nativen FastMCP-Server unter:
|
|
64
|
+
`C:\CentiTools\centicodehelp\centicodehelp_mcp.py`
|
|
65
|
+
|
|
66
|
+
### Verfügbare Tools:
|
|
67
|
+
- `centicodehelp_scan(pfad: str)`: Statische Analyse, liefert JSON-Findings.
|
|
68
|
+
- `centicodehelp_fix(pfad: str, provider: str, model: str)`: Automatische Reparatur mit Backup.
|
|
69
|
+
- `centicodehelp_providers()`: Listet alle KI-Anbieter & Modelle auf.
|
|
70
|
+
*(Aliase `centitool_scan`, `centitool_fix`, `centitool_providers` bleiben abwärtskompatibel erhalten).*
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🔧 Installation
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
cd C:\CentiTools\centicodehelp
|
|
78
|
+
pip install -e .
|
|
79
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
centicodehelp/__init__.py,sha256=HUfIb4VX5nl9xGl32vyPzF7pSBK6Gbxk_t7FqLCAyiE,72
|
|
2
|
+
centicodehelp/ai/llm_client.py,sha256=k6YmnSbNLs7uSSvb4RugutFLtrVJJVACgioSq0Kz_7I,5464
|
|
3
|
+
centicodehelp/ai/prompts.py,sha256=NXDDQ0BLpXGqvZ908JwGZnOUWlCmJbKVqKbanyclDE4,2589
|
|
4
|
+
centicodehelp/ai/providers.py,sha256=k4ilb9l_AyC8kZThgeEHRCBAiKNwlSyYZ6rBM0vNKdg,9207
|
|
5
|
+
centicodehelp/ai/reviewer.py,sha256=Fe6fVdmRtHRYMLEQGaga9aN7J74ZWGq-7lnJ2PQpxn4,5219
|
|
6
|
+
centicodehelp/analysis/binary_analyzer.py,sha256=c-6kXKQ5wa9as5IOHDP0MpgJrtXPJPOIbedG1s5bBL8,5061
|
|
7
|
+
centicodehelp/analysis/detector.py,sha256=oqBvZ1iRe2iRTwXt9j9AhB-gzdJXLrJVnE40NTEAQuM,2307
|
|
8
|
+
centicodehelp/analysis/parser.py,sha256=FStzb0hkvejFniKDSJDBQUpHhNrkcZPl9Ad23HpGSOE,1456
|
|
9
|
+
centicodehelp/analysis/static_analyzer.py,sha256=FAQPtMRo9XpzgsxI0yoPDyBJ0LFP7jElzIO9MAwxTp4,9324
|
|
10
|
+
centicodehelp/cli/banner.py,sha256=NDEEPfFzB1HkMIk6oDgu0zK07um8dHvW_PWgZso3Jmc,3649
|
|
11
|
+
centicodehelp/cli/main.py,sha256=g4qsJ6lmWhaH8SwJn5i-FgdjdJOt3kuLZoNqpQ8IobM,5452
|
|
12
|
+
centicodehelp/cli/theme.py,sha256=FvbbyeX16KlHxz8wBY_GkGYUDhqEPgNzdNTBNf0sa_k,1552
|
|
13
|
+
centicodehelp/cli/commands/ai.py,sha256=zCLrmG8B9nlm43WywEVnc53uUp-EAfAb00UDPteU2aw,5188
|
|
14
|
+
centicodehelp/cli/commands/analyze.py,sha256=MOkdJ0l5jxws4cSvlJg8twCGBGKEec2JQCspkzGWqL8,16297
|
|
15
|
+
centicodehelp/cli/commands/check.py,sha256=sTuNu8ZbuOWGe2QdMAnEskSBXpoYCjRQeLWnzHiCLvo,3457
|
|
16
|
+
centicodehelp/cli/commands/config.py,sha256=NdQgv5Lm85xCTS41mj-HPC0dTj_zNg55KmIsjaXHfE8,2865
|
|
17
|
+
centicodehelp/cli/commands/fix.py,sha256=wgqFOiyIbfK0vGLgycSAc0VCfglFDQjPREQ0prOQ8QE,7077
|
|
18
|
+
centicodehelp/cli/commands/providers.py,sha256=6oCv16HDYhQegXh5levfmX3qFYQ4MzolFJzF3zBPW4w,3811
|
|
19
|
+
centicodehelp/cli/commands/scan.py,sha256=dl3l4k286WNMYMbB2zW1tinCn0k7mhou8SeMY-b4a1E,4693
|
|
20
|
+
centicodehelp/cli/commands/setup.py,sha256=ja4QSZXYLvS4M1WU4F9FS9jjQ2ZlI50B2bHSDERAvaw,4124
|
|
21
|
+
centicodehelp/cli/commands/update.py,sha256=9iDQmjd0V2OUJCGQhbzYn_kgAqcgm1Kajbze2cm62J4,2017
|
|
22
|
+
centicodehelp/core/config.py,sha256=BVbu481lnrEYIcDHxniMN3CYmhXJwWgnxpSt0PTJhAs,2331
|
|
23
|
+
centicodehelp/core/models.py,sha256=oVBIxbdIp2vy4ZZxPFHbNd_vnbtfa1OuK4Vm_X_pFBg,792
|
|
24
|
+
centicodehelp/fixer/applier.py,sha256=MybpqL3xTkacZi5HtuQm6na2X0byudZ11d-OKVBqLNk,673
|
|
25
|
+
centicodehelp/fixer/patcher.py,sha256=K0z4taef0VKi7JaV1wk4pJo2XWcrrE7i6RVZD-pWxwk,1335
|
|
26
|
+
centicodehelp-0.2.0.dist-info/METADATA,sha256=HooZ2WbSYwNO1fMDfvhU6j7vHSck1iBBgHMK8LRTy4k,2207
|
|
27
|
+
centicodehelp-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
28
|
+
centicodehelp-0.2.0.dist-info/entry_points.txt,sha256=mQwtmYE_Vr8lKX8BLaJ1MLDX5Kj_giq0Ti52QlyrnCM,129
|
|
29
|
+
centicodehelp-0.2.0.dist-info/top_level.txt,sha256=2Zqn4Trzsu-6o2vw8RI-bjaiK5GiquMzXCu4rKiksnY,14
|
|
30
|
+
centicodehelp-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
centicodehelp
|