hanuscode 1.0.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.
- hanus/__init__.py +5 -0
- hanus/__main__.py +10 -0
- hanus/action_handlers.py +76 -0
- hanus/action_parser.py +82 -0
- hanus/agent_runner.py +1445 -0
- hanus/analysis/__init__.py +5 -0
- hanus/analysis/debt.py +702 -0
- hanus/analysis/dependencies.py +475 -0
- hanus/cache/__init__.py +5 -0
- hanus/cache/response_cache.py +560 -0
- hanus/config.py +401 -0
- hanus/connectors/__init__.py +19 -0
- hanus/connectors/base.py +114 -0
- hanus/connectors/claude_connector.py +146 -0
- hanus/connectors/gemini_connector.py +141 -0
- hanus/connectors/glm_connector.py +160 -0
- hanus/connectors/ollama_connector.py +174 -0
- hanus/connectors/openai_connector.py +122 -0
- hanus/connectors/registry.py +26 -0
- hanus/context/__init__.py +7 -0
- hanus/context/manager.py +837 -0
- hanus/context/selective.py +626 -0
- hanus/error_recovery/__init__.py +5 -0
- hanus/error_recovery/auto_fix.py +605 -0
- hanus/hooks/__init__.py +5 -0
- hanus/hooks/manager.py +247 -0
- hanus/instincts/__init__.py +44 -0
- hanus/instincts/cli.py +372 -0
- hanus/instincts/detector.py +281 -0
- hanus/instincts/evolver.py +361 -0
- hanus/instincts/manager.py +343 -0
- hanus/instincts/types.py +253 -0
- hanus/logger.py +81 -0
- hanus/memory/__init__.py +8 -0
- hanus/memory/manager.py +265 -0
- hanus/memory/types.py +119 -0
- hanus/monitor.py +341 -0
- hanus/parallel/__init__.py +5 -0
- hanus/parallel/executor.py +300 -0
- hanus/permissions.py +182 -0
- hanus/plan/__init__.py +8 -0
- hanus/plan/mode.py +267 -0
- hanus/plan/models.py +152 -0
- hanus/plugin_manager.py +754 -0
- hanus/plugin_registry.py +391 -0
- hanus/plugins/__init__.py +1 -0
- hanus/plugins/arena.py +630 -0
- hanus/plugins/code_review.py +123 -0
- hanus/plugins/cortex.py +1750 -0
- hanus/plugins/deps_check.py +27 -0
- hanus/plugins/git_ops.py +33 -0
- hanus/plugins/metasploit.py +530 -0
- hanus/plugins/notes.py +583 -0
- hanus/plugins/search_code.py +59 -0
- hanus/plugins/searchsploit.py +495 -0
- hanus/plugins/strategist.py +175 -0
- hanus/plugins/webui.py +5200 -0
- hanus/profiles.py +479 -0
- hanus/profiles_builtin/__init__.py +0 -0
- hanus/profiles_builtin/architect/profile.yaml +12 -0
- hanus/profiles_builtin/architect/system_prompt.txt +71 -0
- hanus/profiles_builtin/deep/profile.yaml +12 -0
- hanus/profiles_builtin/deep/system_prompt.txt +66 -0
- hanus/profiles_builtin/developer/__init__.py +0 -0
- hanus/profiles_builtin/developer/profile.yaml +9 -0
- hanus/profiles_builtin/developer/system_prompt.txt +176 -0
- hanus/profiles_builtin/speed/profile.yaml +12 -0
- hanus/profiles_builtin/speed/system_prompt.txt +51 -0
- hanus/project_tools.py +177 -0
- hanus/query_engine.py +1594 -0
- hanus/rules/__init__.py +237 -0
- hanus/search/__init__.py +5 -0
- hanus/search/semantic.py +596 -0
- hanus/session_manager.py +547 -0
- hanus/skill_manager.py +702 -0
- hanus/skills/__init__.py +4 -0
- hanus/subagent/__init__.py +8 -0
- hanus/subagent/agents/__init__.py +253 -0
- hanus/subagent/manager.py +309 -0
- hanus/subagent/types.py +266 -0
- hanus/suggestions/__init__.py +5 -0
- hanus/suggestions/proactive.py +451 -0
- hanus/tasks/__init__.py +8 -0
- hanus/tasks/manager.py +330 -0
- hanus/tasks/models.py +106 -0
- hanus/terminal_prompt.py +166 -0
- hanus/tools.py +1849 -0
- hanus/ui.py +939 -0
- hanuscode-1.0.0.dist-info/METADATA +1151 -0
- hanuscode-1.0.0.dist-info/RECORD +93 -0
- hanuscode-1.0.0.dist-info/WHEEL +5 -0
- hanuscode-1.0.0.dist-info/entry_points.txt +2 -0
- hanuscode-1.0.0.dist-info/top_level.txt +1 -0
hanus/rules/__init__.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# hanus/rules/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Rules loader and registry.
|
|
4
|
+
|
|
5
|
+
Carga reglas comunes y específicas por lenguaje desde archivos .md
|
|
6
|
+
y las registra para uso del sistema de agentes.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
import re
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Dict, List, Optional
|
|
13
|
+
from enum import Enum
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RuleCategory(Enum):
|
|
17
|
+
"""Categorías de reglas."""
|
|
18
|
+
CODING_STYLE = "coding-style"
|
|
19
|
+
SECURITY = "security"
|
|
20
|
+
TESTING = "testing"
|
|
21
|
+
PATTERNS = "patterns"
|
|
22
|
+
PERFORMANCE = "performance"
|
|
23
|
+
DEVELOPMENT_WORKFLOW = "development-workflow"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RuleLanguage(Enum):
|
|
27
|
+
"""Lenguajes soportados."""
|
|
28
|
+
COMMON = "common"
|
|
29
|
+
PYTHON = "python"
|
|
30
|
+
TYPESCRIPT = "typescript"
|
|
31
|
+
JAVASCRIPT = "javascript"
|
|
32
|
+
GO = "go"
|
|
33
|
+
RUST = "rust"
|
|
34
|
+
JAVA = "java"
|
|
35
|
+
PHP = "php"
|
|
36
|
+
SWIFT = "swift"
|
|
37
|
+
KOTLIN = "kotlin"
|
|
38
|
+
CPP = "cpp"
|
|
39
|
+
CSHARP = "csharp"
|
|
40
|
+
REACT = "react"
|
|
41
|
+
FASTAPI = "fastapi"
|
|
42
|
+
DJANGO = "django"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class Rule:
|
|
47
|
+
"""Representa una regla cargada desde archivo."""
|
|
48
|
+
category: RuleCategory
|
|
49
|
+
language: RuleLanguage
|
|
50
|
+
name: str
|
|
51
|
+
content: str
|
|
52
|
+
file_path: Path
|
|
53
|
+
sections: Dict[str, str] = field(default_factory=dict)
|
|
54
|
+
|
|
55
|
+
def get_section(self, name: str) -> Optional[str]:
|
|
56
|
+
"""Obtiene una sección específica de la regla."""
|
|
57
|
+
return self.sections.get(name)
|
|
58
|
+
|
|
59
|
+
def get_all_sections(self) -> Dict[str, str]:
|
|
60
|
+
"""Obtiene todas las secciones."""
|
|
61
|
+
return self.sections
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class RulesLoader:
|
|
65
|
+
"""Cargador de reglas desde archivos markdown."""
|
|
66
|
+
|
|
67
|
+
def __init__(self, rules_dir: Path = None):
|
|
68
|
+
self.rules_dir = rules_dir or Path(__file__).parent
|
|
69
|
+
self._rules: Dict[str, Rule] = {}
|
|
70
|
+
self._loaded = False
|
|
71
|
+
|
|
72
|
+
def load_all(self, force: bool = False) -> Dict[str, Rule]:
|
|
73
|
+
"""Carga todas las reglas desde los archivos .md."""
|
|
74
|
+
if self._loaded and not force:
|
|
75
|
+
return self._rules
|
|
76
|
+
|
|
77
|
+
self._rules.clear()
|
|
78
|
+
|
|
79
|
+
# Cargar reglas comunes
|
|
80
|
+
common_dir = self.rules_dir / "common"
|
|
81
|
+
if common_dir.exists():
|
|
82
|
+
for rule_file in common_dir.glob("*.md"):
|
|
83
|
+
rule = self._load_rule(rule_file, RuleLanguage.COMMON)
|
|
84
|
+
if rule:
|
|
85
|
+
key = f"common/{rule.name}"
|
|
86
|
+
self._rules[key] = rule
|
|
87
|
+
|
|
88
|
+
# Cargar reglas por lenguaje
|
|
89
|
+
for language in RuleLanguage:
|
|
90
|
+
if language == RuleLanguage.COMMON:
|
|
91
|
+
continue
|
|
92
|
+
lang_dir = self.rules_dir / language.value
|
|
93
|
+
if lang_dir.exists():
|
|
94
|
+
for rule_file in lang_dir.glob("*.md"):
|
|
95
|
+
rule = self._load_rule(rule_file, language)
|
|
96
|
+
if rule:
|
|
97
|
+
key = f"{language.value}/{rule.name}"
|
|
98
|
+
self._rules[key] = rule
|
|
99
|
+
|
|
100
|
+
self._loaded = True
|
|
101
|
+
return self._rules
|
|
102
|
+
|
|
103
|
+
def _load_rule(self, file_path: Path, language: RuleLanguage) -> Optional[Rule]:
|
|
104
|
+
"""Carga una regla desde un archivo .md."""
|
|
105
|
+
try:
|
|
106
|
+
content = file_path.read_text(encoding="utf-8")
|
|
107
|
+
|
|
108
|
+
# Extraer nombre del archivo
|
|
109
|
+
name = file_path.stem
|
|
110
|
+
|
|
111
|
+
# Determinar categoría
|
|
112
|
+
category = self._get_category_from_name(name)
|
|
113
|
+
|
|
114
|
+
# Parsear secciones
|
|
115
|
+
sections = self._parse_sections(content)
|
|
116
|
+
|
|
117
|
+
return Rule(
|
|
118
|
+
category=category,
|
|
119
|
+
language=language,
|
|
120
|
+
name=name,
|
|
121
|
+
content=content,
|
|
122
|
+
file_path=file_path,
|
|
123
|
+
sections=sections,
|
|
124
|
+
)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
print(f"[RulesLoader] Error loading {file_path}: {e}")
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
def _get_category_from_name(self, name: str) -> RuleCategory:
|
|
130
|
+
"""Determina la categoría de la regla desde su nombre."""
|
|
131
|
+
name_lower = name.lower()
|
|
132
|
+
for category in RuleCategory:
|
|
133
|
+
if category.value in name_lower:
|
|
134
|
+
return category
|
|
135
|
+
return RuleCategory.CODING_STYLE # Default
|
|
136
|
+
|
|
137
|
+
def _parse_sections(self, content: str) -> Dict[str, str]:
|
|
138
|
+
"""Parsea las secciones del markdown."""
|
|
139
|
+
sections = {}
|
|
140
|
+
current_section = None
|
|
141
|
+
current_content = []
|
|
142
|
+
|
|
143
|
+
for line in content.split("\n"):
|
|
144
|
+
# Detectar encabezados de sección (##)
|
|
145
|
+
if line.startswith("## "):
|
|
146
|
+
if current_section:
|
|
147
|
+
sections[current_section] = "\n".join(current_content).strip()
|
|
148
|
+
current_section = line[3:].strip()
|
|
149
|
+
current_content = []
|
|
150
|
+
elif current_section:
|
|
151
|
+
current_content.append(line)
|
|
152
|
+
|
|
153
|
+
# Guardar última sección
|
|
154
|
+
if current_section:
|
|
155
|
+
sections[current_section] = "\n".join(current_content).strip()
|
|
156
|
+
|
|
157
|
+
return sections
|
|
158
|
+
|
|
159
|
+
def get_rule(self, language: str, category: str) -> Optional[Rule]:
|
|
160
|
+
"""Obtiene una regla específica."""
|
|
161
|
+
if not self._loaded:
|
|
162
|
+
self.load_all()
|
|
163
|
+
|
|
164
|
+
key = f"{language}/{category}"
|
|
165
|
+
return self._rules.get(key)
|
|
166
|
+
|
|
167
|
+
def get_rules_for_language(self, language: RuleLanguage) -> List[Rule]:
|
|
168
|
+
"""Obtiene todas las reglas para un lenguaje."""
|
|
169
|
+
if not self._loaded:
|
|
170
|
+
self.load_all()
|
|
171
|
+
|
|
172
|
+
return [r for r in self._rules.values() if r.language == language]
|
|
173
|
+
|
|
174
|
+
def get_rules_for_category(self, category: RuleCategory) -> List[Rule]:
|
|
175
|
+
"""Obtiene todas las reglas para una categoría."""
|
|
176
|
+
if not self._loaded:
|
|
177
|
+
self.load_all()
|
|
178
|
+
|
|
179
|
+
return [r for r in self._rules.values() if r.category == category]
|
|
180
|
+
|
|
181
|
+
def get_common_rules(self) -> List[Rule]:
|
|
182
|
+
"""Obtiene todas las reglas comunes."""
|
|
183
|
+
return self.get_rules_for_language(RuleLanguage.COMMON)
|
|
184
|
+
|
|
185
|
+
def get_all_rules(self) -> Dict[str, Rule]:
|
|
186
|
+
"""Obtiene todas las reglas cargadas."""
|
|
187
|
+
if not self._loaded:
|
|
188
|
+
self.load_all()
|
|
189
|
+
return self._rules
|
|
190
|
+
|
|
191
|
+
def get_applicable_rules(self, language: RuleLanguage) -> Dict[str, List[Rule]]:
|
|
192
|
+
"""Obtiene reglas aplicables: comunes + específicas del lenguaje."""
|
|
193
|
+
common = self.get_common_rules()
|
|
194
|
+
specific = self.get_rules_for_language(language)
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
"common": common,
|
|
198
|
+
"language_specific": specific,
|
|
199
|
+
"all": common + specific,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# Instancia global
|
|
204
|
+
_loader: Optional[RulesLoader] = None
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def get_rules_loader(rules_dir: Path = None) -> RulesLoader:
|
|
208
|
+
"""Obtiene el cargador de reglas."""
|
|
209
|
+
global _loader
|
|
210
|
+
if _loader is None:
|
|
211
|
+
_loader = RulesLoader(rules_dir)
|
|
212
|
+
return _loader
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_rule(language: str, category: str) -> Optional[Rule]:
|
|
216
|
+
"""Obtiene una regla específica."""
|
|
217
|
+
return get_rules_loader().get_rule(language, category)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def get_rules_for_language(language: str) -> List[Rule]:
|
|
221
|
+
"""Obtiene todas las reglas para un lenguaje."""
|
|
222
|
+
try:
|
|
223
|
+
lang = RuleLanguage(language.lower())
|
|
224
|
+
except ValueError:
|
|
225
|
+
lang = RuleLanguage.PYTHON # Default
|
|
226
|
+
|
|
227
|
+
return get_rules_loader().get_rules_for_language(lang)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def get_applicable_rules(language: str) -> Dict[str, List[Rule]]:
|
|
231
|
+
"""Obtiene reglas aplicables para un lenguaje."""
|
|
232
|
+
try:
|
|
233
|
+
lang = RuleLanguage(language.lower())
|
|
234
|
+
except ValueError:
|
|
235
|
+
lang = RuleLanguage.PYTHON # Default
|
|
236
|
+
|
|
237
|
+
return get_rules_loader().get_applicable_rules(lang)
|