higpertext-cli 0.8.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.
Files changed (335) hide show
  1. config/adapters_config.json +450 -0
  2. config/antigravity_agent_template.json +31 -0
  3. config/app_config.json +174 -0
  4. config/context_engine.json +33 -0
  5. config/environments/model_defaults.json +5 -0
  6. config/governance/branching_strategy.json +36 -0
  7. config/governance/deployment_gates.json +30 -0
  8. config/governance/guidelines_contract.json +54 -0
  9. config/governance/quality_gates.json +39 -0
  10. config/governance/section_rules.json +22 -0
  11. config/governance/security_guardrails.json +52 -0
  12. config/hooks/README.md +35 -0
  13. config/hooks/custom/test_output_limiter.json +9 -0
  14. config/hooks/global/session_prompt.json +9 -0
  15. config/htx_config.json +24 -0
  16. config/profile_learner.json +18 -0
  17. config/profiles/base_agent.json +40 -0
  18. config/profiles/base_auditor.json +19 -0
  19. config/profiles/base_developer.json +19 -0
  20. config/profiles/base_operator.json +16 -0
  21. config/profiles/global.json +33 -0
  22. config/profiles/software_developer.json +23 -0
  23. config/router_content.json +137 -0
  24. config/semantic_graph.json +66 -0
  25. config/workflows/ado_release_flow.json +38 -0
  26. config/workflows/docs-update.json +33 -0
  27. config/workflows/governance-check.yaml +26 -0
  28. config/workflows/guidelines-sync.json +40 -0
  29. config/workflows/higpertext-build.json +73 -0
  30. config/workflows/higpertext-plan.json +38 -0
  31. config/workflows/higpertext-review.json +41 -0
  32. config/workflows/pr-quality-check.json +56 -0
  33. config/workflows/quality-remediation.json +57 -0
  34. higpertext/__init__.py +18 -0
  35. higpertext/adapters/__init__.py +27 -0
  36. higpertext/adapters/adapter_utils.py +604 -0
  37. higpertext/adapters/claude_adapter/__init__.py +0 -0
  38. higpertext/adapters/claude_adapter/claude_adapter.py +154 -0
  39. higpertext/adapters/copilot_adapter/__init__.py +0 -0
  40. higpertext/adapters/copilot_adapter/copilot_adapter.py +231 -0
  41. higpertext/adapters/gemini_adapter/__init__.py +0 -0
  42. higpertext/adapters/gemini_adapter/gemini_adapter.py +211 -0
  43. higpertext/adapters/llm_formatter.py +46 -0
  44. higpertext/adapters/open_code_adapter/__init__.py +0 -0
  45. higpertext/adapters/open_code_adapter/open_code_adapter.py +480 -0
  46. higpertext/capabilities/capabilities_runner.py +216 -0
  47. higpertext/capabilities/common/agent-builder.json +54 -0
  48. higpertext/capabilities/common/agent-sync.json +34 -0
  49. higpertext/capabilities/common/code-skeletonizer.json +35 -0
  50. higpertext/capabilities/common/commit-report.json +42 -0
  51. higpertext/capabilities/common/context-assembler.json +37 -0
  52. higpertext/capabilities/common/context-budget-report.json +15 -0
  53. higpertext/capabilities/common/dep-manager.json +43 -0
  54. higpertext/capabilities/common/docs-sync.json +14 -0
  55. higpertext/capabilities/common/doctor.json +18 -0
  56. higpertext/capabilities/common/efficiency-meter.json +31 -0
  57. higpertext/capabilities/common/env-catalog.json +13 -0
  58. higpertext/capabilities/common/env-clean.json +14 -0
  59. higpertext/capabilities/common/env-logs.json +16 -0
  60. higpertext/capabilities/common/env-runner.json +23 -0
  61. higpertext/capabilities/common/env-status.json +13 -0
  62. higpertext/capabilities/common/env-stop.json +14 -0
  63. higpertext/capabilities/common/env-template.json +14 -0
  64. higpertext/capabilities/common/error-context-locator.json +23 -0
  65. higpertext/capabilities/common/eval-agent.json +33 -0
  66. higpertext/capabilities/common/file-map.json +17 -0
  67. higpertext/capabilities/common/governance-exception.json +54 -0
  68. higpertext/capabilities/common/graph-query.json +59 -0
  69. higpertext/capabilities/common/graph-rebuild.json +31 -0
  70. higpertext/capabilities/common/graph-visualize.json +37 -0
  71. higpertext/capabilities/common/grep-search.json +176 -0
  72. higpertext/capabilities/common/higpertext-tester.json +25 -0
  73. higpertext/capabilities/common/hook-health.json +19 -0
  74. higpertext/capabilities/common/hook-sync-check.json +19 -0
  75. higpertext/capabilities/common/hooks-manager.json +55 -0
  76. higpertext/capabilities/common/knowledge-asker.json +27 -0
  77. higpertext/capabilities/common/list-rules.json +27 -0
  78. higpertext/capabilities/common/llm-invoke.json +59 -0
  79. higpertext/capabilities/common/load-rules.json +37 -0
  80. higpertext/capabilities/common/memory-manager.json +65 -0
  81. higpertext/capabilities/common/quality-scan.json +21 -0
  82. higpertext/capabilities/common/quality-updater.json +35 -0
  83. higpertext/capabilities/common/rag-index.json +17 -0
  84. higpertext/capabilities/common/report-viewer.json +24 -0
  85. higpertext/capabilities/common/roadmap-report.json +37 -0
  86. higpertext/capabilities/common/scripts/_env_cli.py +65 -0
  87. higpertext/capabilities/common/scripts/agent_builder.py +60 -0
  88. higpertext/capabilities/common/scripts/agent_sync.py +56 -0
  89. higpertext/capabilities/common/scripts/ask_higpertext.py +38 -0
  90. higpertext/capabilities/common/scripts/code_skeletonizer.py +225 -0
  91. higpertext/capabilities/common/scripts/commit_report.py +134 -0
  92. higpertext/capabilities/common/scripts/context_assembler.py +70 -0
  93. higpertext/capabilities/common/scripts/context_budget_report.py +53 -0
  94. higpertext/capabilities/common/scripts/dep_manager.py +81 -0
  95. higpertext/capabilities/common/scripts/docs_sync.py +981 -0
  96. higpertext/capabilities/common/scripts/doctor.py +144 -0
  97. higpertext/capabilities/common/scripts/efficiency_meter.py +83 -0
  98. higpertext/capabilities/common/scripts/env_catalog.py +47 -0
  99. higpertext/capabilities/common/scripts/env_clean.py +30 -0
  100. higpertext/capabilities/common/scripts/env_logs.py +32 -0
  101. higpertext/capabilities/common/scripts/env_runner.py +53 -0
  102. higpertext/capabilities/common/scripts/env_status.py +38 -0
  103. higpertext/capabilities/common/scripts/env_stop.py +30 -0
  104. higpertext/capabilities/common/scripts/env_template.py +73 -0
  105. higpertext/capabilities/common/scripts/error_context_locator.py +138 -0
  106. higpertext/capabilities/common/scripts/eval_agent.py +80 -0
  107. higpertext/capabilities/common/scripts/file_map.py +95 -0
  108. higpertext/capabilities/common/scripts/governance_exception.py +116 -0
  109. higpertext/capabilities/common/scripts/graph_query.py +104 -0
  110. higpertext/capabilities/common/scripts/graph_rebuild.py +107 -0
  111. higpertext/capabilities/common/scripts/graph_visualize.py +76 -0
  112. higpertext/capabilities/common/scripts/grep_search.py +648 -0
  113. higpertext/capabilities/common/scripts/higpertext_tester.py +102 -0
  114. higpertext/capabilities/common/scripts/hook_health.py +149 -0
  115. higpertext/capabilities/common/scripts/hook_sync_check.py +134 -0
  116. higpertext/capabilities/common/scripts/hooks_manager.py +171 -0
  117. higpertext/capabilities/common/scripts/list_rules.py +175 -0
  118. higpertext/capabilities/common/scripts/llm_invoke.py +135 -0
  119. higpertext/capabilities/common/scripts/load_rules.py +379 -0
  120. higpertext/capabilities/common/scripts/memory_manager.py +210 -0
  121. higpertext/capabilities/common/scripts/presentation_engine.py +63 -0
  122. higpertext/capabilities/common/scripts/quality_scan.py +132 -0
  123. higpertext/capabilities/common/scripts/rag_index.py +39 -0
  124. higpertext/capabilities/common/scripts/report_viewer.py +106 -0
  125. higpertext/capabilities/common/scripts/roadmap_report.py +73 -0
  126. higpertext/capabilities/common/scripts/search_router.py +111 -0
  127. higpertext/capabilities/common/scripts/semantic_diff.py +166 -0
  128. higpertext/capabilities/common/scripts/semantic_search.py +43 -0
  129. higpertext/capabilities/common/scripts/session_control.py +136 -0
  130. higpertext/capabilities/common/scripts/smart_read.py +232 -0
  131. higpertext/capabilities/common/scripts/subagent_executor.py +143 -0
  132. higpertext/capabilities/common/scripts/sync_agents.py +353 -0
  133. higpertext/capabilities/common/scripts/task_decomposer.py +78 -0
  134. higpertext/capabilities/common/scripts/telemetry_report.py +36 -0
  135. higpertext/capabilities/common/search-router.json +24 -0
  136. higpertext/capabilities/common/semantic-diff.json +40 -0
  137. higpertext/capabilities/common/semantic-search.json +19 -0
  138. higpertext/capabilities/common/session-clean.json +20 -0
  139. higpertext/capabilities/common/session-start.json +44 -0
  140. higpertext/capabilities/common/smart-read.json +28 -0
  141. higpertext/capabilities/common/subagent-executor.json +25 -0
  142. higpertext/capabilities/common/sync-agents.json +32 -0
  143. higpertext/capabilities/common/task-decomposer.json +37 -0
  144. higpertext/capabilities/common/telemetry-report.json +23 -0
  145. higpertext/capabilities/git/__init__.py +0 -0
  146. higpertext/capabilities/git/committer.json +61 -0
  147. higpertext/capabilities/git/diff.json +33 -0
  148. higpertext/capabilities/git/ls-files.json +44 -0
  149. higpertext/capabilities/git/rm.json +27 -0
  150. higpertext/capabilities/git/scripts/__init__.py +0 -0
  151. higpertext/capabilities/git/scripts/commit_changes.py +1077 -0
  152. higpertext/capabilities/git/scripts/git_diff.py +171 -0
  153. higpertext/capabilities/git/scripts/git_ls_files.py +376 -0
  154. higpertext/capabilities/git/scripts/git_rm.py +62 -0
  155. higpertext/capabilities/security/k8s-auditor.json +33 -0
  156. higpertext/capabilities/security/scripts/k8s_auditor.py +307 -0
  157. higpertext/capabilities/security/scripts/secret_scanner.py +235 -0
  158. higpertext/capabilities/security/secret-scanner.json +32 -0
  159. higpertext/hooks/__init__.py +28 -0
  160. higpertext/hooks/_compat.py +27 -0
  161. higpertext/hooks/hook_tasks/__init__.py +1 -0
  162. higpertext/hooks/hook_tasks/_rules/__init__.py +0 -0
  163. higpertext/hooks/hook_tasks/_rules/bash_rules.py +635 -0
  164. higpertext/hooks/hook_tasks/_rules/context_engine_rule.py +79 -0
  165. higpertext/hooks/hook_tasks/_rules/context_rules.py +199 -0
  166. higpertext/hooks/hook_tasks/_rules/governance_adapter.py +72 -0
  167. higpertext/hooks/hook_tasks/_rules/profile_rules.json +25 -0
  168. higpertext/hooks/hook_tasks/_rules/quality_rules.py +86 -0
  169. higpertext/hooks/hook_tasks/_rules/security_rules.py +214 -0
  170. higpertext/hooks/hook_tasks/_rules/session_rules.py +316 -0
  171. higpertext/hooks/hook_tasks/_rules/telemetry_rules.py +121 -0
  172. higpertext/hooks/hook_tasks/audit_logger_hook.py +28 -0
  173. higpertext/hooks/hook_tasks/hook_bash_guard.py +101 -0
  174. higpertext/hooks/hook_tasks/hook_code_quality.py +48 -0
  175. higpertext/hooks/hook_tasks/hook_context_hint.py +46 -0
  176. higpertext/hooks/hook_tasks/hook_context_manager.py +44 -0
  177. higpertext/hooks/hook_tasks/hook_io.py +122 -0
  178. higpertext/hooks/hook_tasks/hook_loop_guard.py +182 -0
  179. higpertext/hooks/hook_tasks/hook_post_observer.py +54 -0
  180. higpertext/hooks/hook_tasks/hook_read_guard.py +85 -0
  181. higpertext/hooks/hook_tasks/hook_security_guard.py +81 -0
  182. higpertext/hooks/hook_tasks/hook_session_prompt.py +83 -0
  183. higpertext/hooks/hook_tasks/hook_session_stop.py +115 -0
  184. higpertext/hooks/hook_tasks/hook_utils.py +144 -0
  185. higpertext/hooks/hook_tasks/session_guard_hook.py +23 -0
  186. higpertext/hooks/hook_tasks/telemetry_utils.py +176 -0
  187. higpertext/hooks/hook_tasks/test_echo_hook.py +33 -0
  188. higpertext/hooks/hook_tasks/webhook_hook.py +54 -0
  189. higpertext/hooks/hook_tasks/workflow_runner_hook.py +49 -0
  190. higpertext/hooks/hooks_catalog.json +116 -0
  191. higpertext/kernel/__init__.py +63 -0
  192. higpertext/kernel/_compat.py +138 -0
  193. higpertext/kernel/app_config.py +117 -0
  194. higpertext/kernel/application/__init__.py +13 -0
  195. higpertext/kernel/application/agent_registry.py +102 -0
  196. higpertext/kernel/application/capability_manager.py +61 -0
  197. higpertext/kernel/application/commit_reporter.py +247 -0
  198. higpertext/kernel/application/context_builder.py +166 -0
  199. higpertext/kernel/application/context_engine.py +409 -0
  200. higpertext/kernel/application/engine.py +41 -0
  201. higpertext/kernel/application/env_runtime.py +174 -0
  202. higpertext/kernel/application/environment_manager.py +154 -0
  203. higpertext/kernel/application/governance.py +192 -0
  204. higpertext/kernel/application/hook_registry.py +102 -0
  205. higpertext/kernel/application/hook_renderer.py +720 -0
  206. higpertext/kernel/application/ports.py +49 -0
  207. higpertext/kernel/application/profile_learner.py +358 -0
  208. higpertext/kernel/application/profile_service.py +205 -0
  209. higpertext/kernel/application/profile_services.py +6 -0
  210. higpertext/kernel/application/profile_use_cases.py +93 -0
  211. higpertext/kernel/application/rag_service.py +75 -0
  212. higpertext/kernel/application/roadmap_reporter.py +178 -0
  213. higpertext/kernel/application/semantic_engine.py +258 -0
  214. higpertext/kernel/application/session_services.py +33 -0
  215. higpertext/kernel/application/skill_hook_compiler.py +85 -0
  216. higpertext/kernel/application/telemetry.py +326 -0
  217. higpertext/kernel/application/workflow_manager.py +176 -0
  218. higpertext/kernel/config_paths.py +66 -0
  219. higpertext/kernel/domain/__init__.py +12 -0
  220. higpertext/kernel/domain/agent_registry.py +23 -0
  221. higpertext/kernel/domain/commit_reporter.py +155 -0
  222. higpertext/kernel/domain/compilers.py +7 -0
  223. higpertext/kernel/domain/context_engine.py +319 -0
  224. higpertext/kernel/domain/entities.py +51 -0
  225. higpertext/kernel/domain/env_runtime.py +62 -0
  226. higpertext/kernel/domain/governance.py +198 -0
  227. higpertext/kernel/domain/hook_models.py +29 -0
  228. higpertext/kernel/domain/profile_learner.py +186 -0
  229. higpertext/kernel/domain/rag.py +70 -0
  230. higpertext/kernel/domain/repositories.py +8 -0
  231. higpertext/kernel/domain/roadmap_reporter.py +80 -0
  232. higpertext/kernel/domain/semantic_engine.py +107 -0
  233. higpertext/kernel/engine.py +42 -0
  234. higpertext/kernel/htx_resolver.py +69 -0
  235. higpertext/kernel/infrastructure/__init__.py +13 -0
  236. higpertext/kernel/infrastructure/agent_registry.py +40 -0
  237. higpertext/kernel/infrastructure/cache/capability_cache.py +319 -0
  238. higpertext/kernel/infrastructure/capability_helper.py +40 -0
  239. higpertext/kernel/infrastructure/cli/__init__.py +1 -0
  240. higpertext/kernel/infrastructure/cli/agent_commands.py +62 -0
  241. higpertext/kernel/infrastructure/cli/arguments.py +39 -0
  242. higpertext/kernel/infrastructure/cli/capability_command_builder.py +86 -0
  243. higpertext/kernel/infrastructure/cli/capability_task_service.py +234 -0
  244. higpertext/kernel/infrastructure/cli/cli_search.py +234 -0
  245. higpertext/kernel/infrastructure/cli/parameter_contracts.py +83 -0
  246. higpertext/kernel/infrastructure/cli/parser_builder.py +122 -0
  247. higpertext/kernel/infrastructure/cli/profile_commands.py +89 -0
  248. higpertext/kernel/infrastructure/cli/roadmap_commands.py +117 -0
  249. higpertext/kernel/infrastructure/cli/router.py +1110 -0
  250. higpertext/kernel/infrastructure/cli/session_commands.py +36 -0
  251. higpertext/kernel/infrastructure/cli/task_commands.py +23 -0
  252. higpertext/kernel/infrastructure/cli/task_result_reporter.py +56 -0
  253. higpertext/kernel/infrastructure/cli/workflow_commands.py +25 -0
  254. higpertext/kernel/infrastructure/compilers/__init__.py +3 -0
  255. higpertext/kernel/infrastructure/compilers/factory.py +27 -0
  256. higpertext/kernel/infrastructure/compilers/graph_compiler.py +20 -0
  257. higpertext/kernel/infrastructure/compilers/guide_compiler.py +50 -0
  258. higpertext/kernel/infrastructure/compilers/hook_compiler.py +69 -0
  259. higpertext/kernel/infrastructure/compilers/playbook_compiler.py +154 -0
  260. higpertext/kernel/infrastructure/context_engine.py +303 -0
  261. higpertext/kernel/infrastructure/database/local_vector_store.py +99 -0
  262. higpertext/kernel/infrastructure/deployment/__init__.py +1 -0
  263. higpertext/kernel/infrastructure/deployment/resource_deployer.py +283 -0
  264. higpertext/kernel/infrastructure/diagnostics/__init__.py +1 -0
  265. higpertext/kernel/infrastructure/diagnostics/health.py +191 -0
  266. higpertext/kernel/infrastructure/env_runtime.py +227 -0
  267. higpertext/kernel/infrastructure/execution/__init__.py +1 -0
  268. higpertext/kernel/infrastructure/execution/parallel.py +188 -0
  269. higpertext/kernel/infrastructure/execution/resilience.py +155 -0
  270. higpertext/kernel/infrastructure/file_repositories.py +213 -0
  271. higpertext/kernel/infrastructure/governance.py +198 -0
  272. higpertext/kernel/infrastructure/hook_config_loader.py +53 -0
  273. higpertext/kernel/infrastructure/hook_webhook_dispatcher.py +61 -0
  274. higpertext/kernel/infrastructure/hook_workflow_bridge.py +60 -0
  275. higpertext/kernel/infrastructure/llm/__init__.py +6 -0
  276. higpertext/kernel/infrastructure/llm/provider.py +46 -0
  277. higpertext/kernel/infrastructure/llm/providers/__init__.py +0 -0
  278. higpertext/kernel/infrastructure/llm/providers/anthropic_provider.py +94 -0
  279. higpertext/kernel/infrastructure/llm/providers/gemini_embeddings.py +74 -0
  280. higpertext/kernel/infrastructure/llm/providers/gemini_provider.py +101 -0
  281. higpertext/kernel/infrastructure/llm/providers/ollama_provider.py +110 -0
  282. higpertext/kernel/infrastructure/llm/providers/openai_provider.py +98 -0
  283. higpertext/kernel/infrastructure/llm/registry.py +81 -0
  284. higpertext/kernel/infrastructure/logger.py +303 -0
  285. higpertext/kernel/infrastructure/output_store.py +70 -0
  286. higpertext/kernel/infrastructure/parser/__init__.py +1 -0
  287. higpertext/kernel/infrastructure/parser/code_chunker.py +144 -0
  288. higpertext/kernel/infrastructure/parser/language/__init__.py +14 -0
  289. higpertext/kernel/infrastructure/parser/language/base.py +41 -0
  290. higpertext/kernel/infrastructure/parser/language/powershell_parser.py +35 -0
  291. higpertext/kernel/infrastructure/parser/language/python_parser.py +98 -0
  292. higpertext/kernel/infrastructure/parser/language/typescript_parser.py +91 -0
  293. higpertext/kernel/infrastructure/parser/semantic_graph.py +409 -0
  294. higpertext/kernel/infrastructure/presentation/__init__.py +1 -0
  295. higpertext/kernel/infrastructure/presentation/html_renderer.py +137 -0
  296. higpertext/kernel/infrastructure/presentation/markdown_renderer.py +84 -0
  297. higpertext/kernel/infrastructure/presentation/markdown_report_renderer.py +97 -0
  298. higpertext/kernel/infrastructure/profile_store.py +28 -0
  299. higpertext/kernel/infrastructure/semantic_engine.py +289 -0
  300. higpertext/kernel/infrastructure/telemetry_reporter.py +132 -0
  301. higpertext/kernel/infrastructure/validation/__init__.py +1 -0
  302. higpertext/kernel/infrastructure/validation/contract_validator.py +163 -0
  303. higpertext/kernel/pkg_resources.py +38 -0
  304. higpertext/kernel/session_manager.py +319 -0
  305. higpertext/templates/env/generic-shell.yaml +21 -0
  306. higpertext/templates/env/node-vitest.yaml +27 -0
  307. higpertext/templates/env/python-pytest.yaml +29 -0
  308. higpertext/templates/html/commit_body.html +20 -0
  309. higpertext/templates/html/commit_diff.html +4 -0
  310. higpertext/templates/html/commit_index.html +29 -0
  311. higpertext/templates/html/commit_layer.html +11 -0
  312. higpertext/templates/html/commit_shell.html +28 -0
  313. higpertext/templates/html/graph_visualize.html +86 -0
  314. higpertext/templates/html/roadmap_body.html +12 -0
  315. higpertext/templates/html/roadmap_phase.html +5 -0
  316. higpertext/templates/html/roadmap_shell.html +29 -0
  317. higpertext/templates/markdown/commit_report.md +18 -0
  318. higpertext/templates/markdown/efficiency_report.md +12 -0
  319. higpertext/templates/markdown/roadmap_report.md +25 -0
  320. higpertext/templates/skills/best-practices.md +7 -0
  321. higpertext/templates/skills/clean-code.md +8 -0
  322. higpertext/templates/skills/ddd-standards.md +7 -0
  323. higpertext/templates/skills/tdd-practices.md +7 -0
  324. higpertext/templates/subagents/architect.md +7 -0
  325. higpertext/templates/subagents/test-engineer.md +7 -0
  326. higpertext/templates/workflows/build.json +23 -0
  327. higpertext/templates/workflows/compact.json +21 -0
  328. higpertext/templates/workflows/plan.json +59 -0
  329. higpertext/templates/workflows/review.json +26 -0
  330. higpertext/templates/workflows/spec.json +27 -0
  331. higpertext_cli-0.8.0.dist-info/METADATA +35 -0
  332. higpertext_cli-0.8.0.dist-info/RECORD +335 -0
  333. higpertext_cli-0.8.0.dist-info/WHEEL +5 -0
  334. higpertext_cli-0.8.0.dist-info/entry_points.txt +2 -0
  335. higpertext_cli-0.8.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,60 @@
1
+ """WorkflowHookBridge — traduce workflow_hooks de hooks_config.json a hooks ejecutables."""
2
+
3
+ from __future__ import annotations
4
+ from pathlib import Path
5
+ from dataclasses import dataclass
6
+
7
+ from higpertext.kernel.infrastructure.hook_config_loader import load_hooks_config
8
+
9
+
10
+ @dataclass
11
+ class WorkflowHookEntry:
12
+ id: str
13
+ workflow_id: str
14
+ event: str
15
+ matcher: str
16
+ description: str
17
+ enabled: bool
18
+ assistants: list[str]
19
+ profiles: list[str]
20
+
21
+
22
+ class WorkflowHookBridge:
23
+ def __init__(self, project_root: Path) -> None:
24
+ self.project_root = project_root
25
+
26
+ def get_active_workflow_hooks(self, assistant: str, profile: str) -> list[WorkflowHookEntry]:
27
+ config = self._load()
28
+ result: list[WorkflowHookEntry] = []
29
+ for raw in config.get("workflow_hooks", []):
30
+ if not raw.get("enabled", False):
31
+ continue
32
+ allowed_a = raw.get("assistants", [])
33
+ if allowed_a and assistant not in allowed_a:
34
+ continue
35
+ allowed_p = raw.get("profiles", [])
36
+ if allowed_p and profile not in allowed_p:
37
+ continue
38
+ result.append(
39
+ WorkflowHookEntry(
40
+ id=raw["id"],
41
+ workflow_id=raw["workflow_id"],
42
+ event=raw["event"],
43
+ matcher=raw.get("matcher", ""),
44
+ description=raw.get("description", ""),
45
+ enabled=raw.get("enabled", False),
46
+ assistants=raw.get("assistants", []),
47
+ profiles=raw.get("profiles", []),
48
+ )
49
+ )
50
+ return result
51
+
52
+ def to_hook_script_args(self, entry: WorkflowHookEntry) -> str:
53
+ """Genera el comando de shell que ejecuta el workflow desde el hook."""
54
+ return (
55
+ f"python3 src/higpertext/hooks/hook_tasks/workflow_runner_hook.py "
56
+ f"--workflow {entry.workflow_id}"
57
+ )
58
+
59
+ def _load(self) -> dict:
60
+ return load_hooks_config(self.project_root)
@@ -0,0 +1,6 @@
1
+ """LLM infrastructure — provider protocol, registry, and implementations."""
2
+
3
+ from .provider import LLMProvider, LLMResponse
4
+ from .registry import LLMRegistry
5
+
6
+ __all__ = ["LLMProvider", "LLMResponse", "LLMRegistry"]
@@ -0,0 +1,46 @@
1
+ """LLMProvider Protocol — contrato que todo provider debe implementar."""
2
+
3
+ from __future__ import annotations
4
+ from dataclasses import dataclass, field
5
+ from typing import Iterator, Protocol, runtime_checkable
6
+
7
+
8
+ @dataclass
9
+ class LLMResponse:
10
+ content: str
11
+ model: str
12
+ provider: str
13
+ input_tokens: int = 0
14
+ output_tokens: int = 0
15
+ metadata: dict = field(default_factory=dict)
16
+
17
+
18
+ @runtime_checkable
19
+ class LLMProvider(Protocol):
20
+ """Contrato de provider LLM. Soporta completion y streaming."""
21
+
22
+ provider_name: str
23
+
24
+ def complete(
25
+ self,
26
+ prompt: str,
27
+ *,
28
+ system: str = "",
29
+ model: str = "",
30
+ max_tokens: int = 1024,
31
+ temperature: float = 0.7,
32
+ **kwargs,
33
+ ) -> LLMResponse: ...
34
+
35
+ def stream(
36
+ self,
37
+ prompt: str,
38
+ *,
39
+ system: str = "",
40
+ model: str = "",
41
+ max_tokens: int = 1024,
42
+ temperature: float = 0.7,
43
+ **kwargs,
44
+ ) -> Iterator[str]: ...
45
+
46
+ def list_models(self) -> list[str]: ...
@@ -0,0 +1,94 @@
1
+ """AnthropicProvider — implementación LLMProvider para Anthropic Claude."""
2
+
3
+ from __future__ import annotations
4
+ import os
5
+ from typing import Iterator
6
+
7
+ from higpertext.kernel.infrastructure.llm.provider import LLMProvider, LLMResponse
8
+
9
+
10
+ class AnthropicProvider:
11
+ provider_name = "anthropic"
12
+
13
+ def __init__(self, config: dict | None = None) -> None:
14
+ self._config = config or {}
15
+ self._default_model = self._config.get("model", "")
16
+ self._client = None
17
+
18
+ def _resolve_model(self, model: str) -> str:
19
+ resolved_model = model or self._default_model
20
+ if not resolved_model:
21
+ raise ValueError("Modelo Anthropic no definido. Indica --model o HIGPERTEXT_LLM_MODEL.")
22
+ return resolved_model
23
+
24
+ def _get_client(self):
25
+ if self._client is None:
26
+ try:
27
+ import anthropic
28
+ except ImportError:
29
+ raise ImportError("Instala el SDK: pip install anthropic")
30
+ api_key = os.environ.get("ANTHROPIC_API_KEY") or self._config.get("api_key", "")
31
+ if not api_key:
32
+ raise ValueError("ANTHROPIC_API_KEY no está definida en el entorno")
33
+ self._client = anthropic.Anthropic(api_key=api_key)
34
+ return self._client
35
+
36
+ def complete(
37
+ self,
38
+ prompt: str,
39
+ *,
40
+ system: str = "",
41
+ model: str = "",
42
+ max_tokens: int = 1024,
43
+ temperature: float = 0.7,
44
+ **kwargs,
45
+ ) -> LLMResponse:
46
+ client = self._get_client()
47
+ resolved_model = self._resolve_model(model)
48
+ msg = client.messages.create(
49
+ model=resolved_model,
50
+ max_tokens=max_tokens,
51
+ system=system or None,
52
+ messages=[{"role": "user", "content": prompt}],
53
+ temperature=temperature,
54
+ )
55
+ content = msg.content[0].text if msg.content else ""
56
+ return LLMResponse(
57
+ content=content,
58
+ model=resolved_model,
59
+ provider=self.provider_name,
60
+ input_tokens=msg.usage.input_tokens,
61
+ output_tokens=msg.usage.output_tokens,
62
+ )
63
+
64
+ def stream(
65
+ self,
66
+ prompt: str,
67
+ *,
68
+ system: str = "",
69
+ model: str = "",
70
+ max_tokens: int = 1024,
71
+ temperature: float = 0.7,
72
+ **kwargs,
73
+ ) -> Iterator[str]:
74
+ client = self._get_client()
75
+ resolved_model = self._resolve_model(model)
76
+ with client.messages.stream(
77
+ model=resolved_model,
78
+ max_tokens=max_tokens,
79
+ system=system or None,
80
+ messages=[{"role": "user", "content": prompt}],
81
+ temperature=temperature,
82
+ ) as stream:
83
+ for text in stream.text_stream:
84
+ yield text
85
+
86
+ def list_models(self) -> list[str]:
87
+ return [
88
+ "claude-sonnet-4-6",
89
+ "claude-opus-4-8",
90
+ "claude-haiku-4-5-20251001",
91
+ ]
92
+
93
+
94
+ assert isinstance(AnthropicProvider(), LLMProvider)
@@ -0,0 +1,74 @@
1
+ """Gemini Embedding Provider implementation using native urllib requests."""
2
+
3
+ from __future__ import annotations
4
+ import json
5
+ import urllib.request
6
+ import urllib.error
7
+ from pathlib import Path
8
+ from higpertext.kernel.domain.rag import IEmbeddingProvider
9
+
10
+
11
+ class GeminiEmbeddingProvider(IEmbeddingProvider):
12
+ """Generates text embeddings using Google's Gemini API."""
13
+
14
+ def __init__(self, project_root: Path) -> None:
15
+ self.project_root = project_root
16
+ self._api_key = self._load_api_key()
17
+
18
+ def _load_api_key(self) -> str:
19
+ # Intentar cargar desde el entorno
20
+ import os
21
+ key = os.environ.get("GEMINI_API_KEY")
22
+ if key:
23
+ return key
24
+
25
+ # Intentar leer del environment.json
26
+ env_file = self.project_root / ".higpertext" / "config" / "environment.json"
27
+ if env_file.exists():
28
+ try:
29
+ data = json.loads(env_file.read_text(encoding="utf-8"))
30
+ return data.get("GEMINI_API_KEY", "")
31
+ except (OSError, json.JSONDecodeError):
32
+ pass
33
+ return ""
34
+
35
+ def get_embedding(self, text: str) -> list[float]:
36
+ if not self._api_key:
37
+ raise ValueError("[ERROR] No se configuró la variable GEMINI_API_KEY para RAG.")
38
+
39
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004:embedContent?key={self._api_key}"
40
+ payload = {
41
+ "model": "models/text-embedding-004",
42
+ "content": {
43
+ "parts": [{"text": text}]
44
+ }
45
+ }
46
+
47
+ req = urllib.request.Request(
48
+ url,
49
+ data=json.dumps(payload).encode("utf-8"),
50
+ headers={"Content-Type": "application/json"},
51
+ method="POST"
52
+ )
53
+
54
+ try:
55
+ with urllib.request.urlopen(req, timeout=10) as response:
56
+ res_data = json.loads(response.read().decode("utf-8"))
57
+ return res_data["embedding"]["values"]
58
+ except urllib.error.HTTPError as e:
59
+ err_body = e.read().decode("utf-8")
60
+ raise RuntimeError(f"[ERROR] API de Embeddings devolvió HTTP {e.code}: {err_body}")
61
+ except Exception as e:
62
+ raise RuntimeError(f"[ERROR] Falló conexión a la API de Embeddings: {e}")
63
+
64
+ def get_embeddings_batch(self, texts: list[str]) -> list[list[float]]:
65
+ # La API de Gemini permite procesar listas si se llama adecuadamente o secuencial.
66
+ # Por seguridad y límites de API, lo implementamos secuencial pero mapeado.
67
+ embeddings: list[list[float]] = []
68
+ for text in texts:
69
+ if not text.strip():
70
+ # Embedding vacío por defecto
71
+ embeddings.append([0.0] * 768)
72
+ else:
73
+ embeddings.append(self.get_embedding(text))
74
+ return embeddings
@@ -0,0 +1,101 @@
1
+ """GeminiProvider — implementación LLMProvider para Google Gemini."""
2
+
3
+ from __future__ import annotations
4
+ import os
5
+ from typing import Iterator
6
+
7
+ from higpertext.kernel.infrastructure.llm.provider import LLMProvider, LLMResponse
8
+
9
+
10
+ class GeminiProvider:
11
+ provider_name = "gemini"
12
+
13
+ def __init__(self, config: dict | None = None) -> None:
14
+ self._config = config or {}
15
+ self._default_model = self._config.get("model", "")
16
+ self._client = None
17
+
18
+ def _resolve_model(self, model: str) -> str:
19
+ resolved_model = model or self._default_model
20
+ if not resolved_model:
21
+ raise ValueError("Modelo Gemini no definido. Indica --model o HIGPERTEXT_LLM_MODEL.")
22
+ return resolved_model
23
+
24
+ def _get_client(self):
25
+ if self._client is None:
26
+ try:
27
+ from google import genai
28
+ except ImportError:
29
+ raise ImportError("Instala el SDK: pip install google-genai")
30
+ api_key = os.environ.get("GEMINI_API_KEY") or self._config.get("api_key", "")
31
+ if not api_key:
32
+ raise ValueError("GEMINI_API_KEY no está definida en el entorno")
33
+ self._client = genai.Client(api_key=api_key)
34
+ return self._client
35
+
36
+ def complete(
37
+ self,
38
+ prompt: str,
39
+ *,
40
+ system: str = "",
41
+ model: str = "",
42
+ max_tokens: int = 1024,
43
+ temperature: float = 0.7,
44
+ **kwargs,
45
+ ) -> LLMResponse:
46
+ from google.genai import types
47
+
48
+ client = self._get_client()
49
+ resolved_model = self._resolve_model(model)
50
+ config = types.GenerateContentConfig(
51
+ max_output_tokens=max_tokens,
52
+ temperature=temperature,
53
+ system_instruction=system or None,
54
+ )
55
+ resp = client.models.generate_content(
56
+ model=resolved_model,
57
+ contents=prompt,
58
+ config=config,
59
+ )
60
+ content = resp.text or ""
61
+ usage = resp.usage_metadata
62
+ return LLMResponse(
63
+ content=content,
64
+ model=resolved_model,
65
+ provider=self.provider_name,
66
+ input_tokens=usage.prompt_token_count if usage else 0,
67
+ output_tokens=usage.candidates_token_count if usage else 0,
68
+ )
69
+
70
+ def stream(
71
+ self,
72
+ prompt: str,
73
+ *,
74
+ system: str = "",
75
+ model: str = "",
76
+ max_tokens: int = 1024,
77
+ temperature: float = 0.7,
78
+ **kwargs,
79
+ ) -> Iterator[str]:
80
+ from google.genai import types
81
+
82
+ client = self._get_client()
83
+ resolved_model = self._resolve_model(model)
84
+ config = types.GenerateContentConfig(
85
+ max_output_tokens=max_tokens,
86
+ temperature=temperature,
87
+ system_instruction=system or None,
88
+ )
89
+ for chunk in client.models.generate_content_stream(
90
+ model=resolved_model,
91
+ contents=prompt,
92
+ config=config,
93
+ ):
94
+ if chunk.text:
95
+ yield chunk.text
96
+
97
+ def list_models(self) -> list[str]:
98
+ return ["gemini-2.0-flash", "gemini-1.5-pro", "gemini-1.5-flash"]
99
+
100
+
101
+ assert isinstance(GeminiProvider(), LLMProvider)
@@ -0,0 +1,110 @@
1
+ """OllamaProvider — implementación LLMProvider para Ollama (Llama local)."""
2
+
3
+ from __future__ import annotations
4
+ import json
5
+ import urllib.request
6
+ import urllib.error
7
+ from typing import Iterator
8
+
9
+ from higpertext.kernel.infrastructure.llm.provider import LLMProvider, LLMResponse
10
+ from higpertext.kernel.app_config import OLLAMA_BASE_URL as _DEFAULT_BASE_URL
11
+
12
+
13
+ class OllamaProvider:
14
+ provider_name = "ollama"
15
+
16
+ def __init__(self, config: dict | None = None) -> None:
17
+ self._config = config or {}
18
+ self._default_model = self._config.get("model", "")
19
+ self._base_url = self._config.get("base_url", _DEFAULT_BASE_URL).rstrip("/")
20
+
21
+ def _resolve_model(self, model: str) -> str:
22
+ resolved_model = model or self._default_model
23
+ if not resolved_model:
24
+ raise ValueError("Modelo Ollama no definido. Indica --model o HIGPERTEXT_LLM_MODEL.")
25
+ return resolved_model
26
+
27
+ def _post(self, endpoint: str, payload: dict) -> urllib.request.http.client.HTTPResponse:
28
+ url = f"{self._base_url}{endpoint}"
29
+ data = json.dumps(payload).encode("utf-8")
30
+ req = urllib.request.Request(
31
+ url,
32
+ data=data,
33
+ headers={"Content-Type": "application/json"},
34
+ method="POST",
35
+ )
36
+ return urllib.request.urlopen(req, timeout=120) # nosec B310
37
+
38
+ def complete(
39
+ self,
40
+ prompt: str,
41
+ *,
42
+ system: str = "",
43
+ model: str = "",
44
+ max_tokens: int = 1024,
45
+ temperature: float = 0.7,
46
+ **kwargs,
47
+ ) -> LLMResponse:
48
+ resolved_model = self._resolve_model(model)
49
+ messages = []
50
+ if system:
51
+ messages.append({"role": "system", "content": system})
52
+ messages.append({"role": "user", "content": prompt})
53
+ payload = {
54
+ "model": resolved_model,
55
+ "messages": messages,
56
+ "stream": False,
57
+ "options": {"temperature": temperature, "num_predict": max_tokens},
58
+ }
59
+ with self._post("/api/chat", payload) as resp:
60
+ data = json.loads(resp.read().decode("utf-8"))
61
+ content = data.get("message", {}).get("content", "")
62
+ return LLMResponse(
63
+ content=content,
64
+ model=resolved_model,
65
+ provider=self.provider_name,
66
+ input_tokens=data.get("prompt_eval_count", 0),
67
+ output_tokens=data.get("eval_count", 0),
68
+ )
69
+
70
+ def stream(
71
+ self,
72
+ prompt: str,
73
+ *,
74
+ system: str = "",
75
+ model: str = "",
76
+ max_tokens: int = 1024,
77
+ temperature: float = 0.7,
78
+ **kwargs,
79
+ ) -> Iterator[str]:
80
+ resolved_model = self._resolve_model(model)
81
+ messages = []
82
+ if system:
83
+ messages.append({"role": "system", "content": system})
84
+ messages.append({"role": "user", "content": prompt})
85
+ payload = {
86
+ "model": resolved_model,
87
+ "messages": messages,
88
+ "stream": True,
89
+ "options": {"temperature": temperature, "num_predict": max_tokens},
90
+ }
91
+ with self._post("/api/chat", payload) as resp:
92
+ for line in resp:
93
+ chunk = json.loads(line.decode("utf-8"))
94
+ text = chunk.get("message", {}).get("content", "")
95
+ if text:
96
+ yield text
97
+ if chunk.get("done"):
98
+ break
99
+
100
+ def list_models(self) -> list[str]:
101
+ try:
102
+ url = f"{self._base_url}/api/tags"
103
+ with urllib.request.urlopen(url, timeout=5) as resp: # nosec B310
104
+ data = json.loads(resp.read().decode("utf-8"))
105
+ return [m["name"] for m in data.get("models", [])]
106
+ except Exception:
107
+ return []
108
+
109
+
110
+ assert isinstance(OllamaProvider(), LLMProvider)
@@ -0,0 +1,98 @@
1
+ """OpenAIProvider — implementación LLMProvider para OpenAI."""
2
+
3
+ from __future__ import annotations
4
+ import os
5
+ from typing import Iterator
6
+
7
+ from higpertext.kernel.infrastructure.llm.provider import LLMProvider, LLMResponse
8
+
9
+
10
+ class OpenAIProvider:
11
+ provider_name = "openai"
12
+
13
+ def __init__(self, config: dict | None = None) -> None:
14
+ self._config = config or {}
15
+ self._default_model = self._config.get("model", "")
16
+ self._client = None
17
+
18
+ def _resolve_model(self, model: str) -> str:
19
+ resolved_model = model or self._default_model
20
+ if not resolved_model:
21
+ raise ValueError("Modelo OpenAI no definido. Indica --model o HIGPERTEXT_LLM_MODEL.")
22
+ return resolved_model
23
+
24
+ def _get_client(self):
25
+ if self._client is None:
26
+ try:
27
+ import openai
28
+ except ImportError:
29
+ raise ImportError("Instala el SDK: pip install openai")
30
+ api_key = os.environ.get("OPENAI_API_KEY") or self._config.get("api_key", "")
31
+ if not api_key:
32
+ raise ValueError("OPENAI_API_KEY no está definida en el entorno")
33
+ self._client = openai.OpenAI(api_key=api_key)
34
+ return self._client
35
+
36
+ def complete(
37
+ self,
38
+ prompt: str,
39
+ *,
40
+ system: str = "",
41
+ model: str = "",
42
+ max_tokens: int = 1024,
43
+ temperature: float = 0.7,
44
+ **kwargs,
45
+ ) -> LLMResponse:
46
+ client = self._get_client()
47
+ resolved_model = self._resolve_model(model)
48
+ messages = []
49
+ if system:
50
+ messages.append({"role": "system", "content": system})
51
+ messages.append({"role": "user", "content": prompt})
52
+ resp = client.chat.completions.create(
53
+ model=resolved_model,
54
+ messages=messages,
55
+ max_tokens=max_tokens,
56
+ temperature=temperature,
57
+ )
58
+ content = resp.choices[0].message.content or ""
59
+ return LLMResponse(
60
+ content=content,
61
+ model=resolved_model,
62
+ provider=self.provider_name,
63
+ input_tokens=resp.usage.prompt_tokens if resp.usage else 0,
64
+ output_tokens=resp.usage.completion_tokens if resp.usage else 0,
65
+ )
66
+
67
+ def stream(
68
+ self,
69
+ prompt: str,
70
+ *,
71
+ system: str = "",
72
+ model: str = "",
73
+ max_tokens: int = 1024,
74
+ temperature: float = 0.7,
75
+ **kwargs,
76
+ ) -> Iterator[str]:
77
+ client = self._get_client()
78
+ resolved_model = self._resolve_model(model)
79
+ messages = []
80
+ if system:
81
+ messages.append({"role": "system", "content": system})
82
+ messages.append({"role": "user", "content": prompt})
83
+ for chunk in client.chat.completions.create(
84
+ model=resolved_model,
85
+ messages=messages,
86
+ max_tokens=max_tokens,
87
+ temperature=temperature,
88
+ stream=True,
89
+ ):
90
+ delta = chunk.choices[0].delta.content
91
+ if delta:
92
+ yield delta
93
+
94
+ def list_models(self) -> list[str]:
95
+ return ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-3.5-turbo"]
96
+
97
+
98
+ assert isinstance(OpenAIProvider(), LLMProvider)
@@ -0,0 +1,81 @@
1
+ """LLMRegistry — resuelve e instancia el provider correcto por nombre."""
2
+
3
+ from __future__ import annotations
4
+ from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ from typing import TYPE_CHECKING
9
+
10
+ if TYPE_CHECKING:
11
+ from .provider import LLMProvider
12
+
13
+
14
+ _PROVIDER_MODULES: dict[str, tuple[str, str]] = {
15
+ "anthropic": (
16
+ "kernel.infrastructure.llm.providers.anthropic_provider",
17
+ "AnthropicProvider",
18
+ ),
19
+ "openai": ("kernel.infrastructure.llm.providers.openai_provider", "OpenAIProvider"),
20
+ "gemini": ("kernel.infrastructure.llm.providers.gemini_provider", "GeminiProvider"),
21
+ "ollama": ("kernel.infrastructure.llm.providers.ollama_provider", "OllamaProvider"),
22
+ }
23
+
24
+
25
+ class LLMRegistry:
26
+ """Resuelve el provider LLM desde environment.json o variable de entorno."""
27
+
28
+ def __init__(self, project_root: Path | None = None) -> None:
29
+ self._root = project_root or Path.cwd()
30
+ self._cache: dict[str, "LLMProvider"] = {}
31
+
32
+ def _load_env_config(self) -> dict:
33
+ env_path = self._root / WORKSPACE_DIR_NAME / "config" / "environment.json"
34
+ try:
35
+ return json.loads(env_path.read_text(encoding="utf-8"))
36
+ except (OSError, json.JSONDecodeError):
37
+ return {}
38
+
39
+ def default_provider(self) -> str:
40
+ env_var = os.environ.get("HIGPERTEXT_LLM_PROVIDER")
41
+ if env_var:
42
+ return env_var.lower()
43
+ cfg = self._load_env_config()
44
+ return cfg.get("llm", {}).get("default_provider", "")
45
+
46
+ def default_model(self, provider: str) -> str:
47
+ env_var = os.environ.get("HIGPERTEXT_LLM_MODEL")
48
+ if env_var:
49
+ return env_var
50
+ cfg = self._load_env_config()
51
+ provider_cfg = cfg.get("llm", {}).get("providers", {}).get(provider, {})
52
+ return provider_cfg.get("model", "")
53
+
54
+ def provider_config(self, provider: str) -> dict:
55
+ cfg = self._load_env_config()
56
+ return cfg.get("llm", {}).get("providers", {}).get(provider, {})
57
+
58
+ def resolve(self, provider_name: str | None = None) -> "LLMProvider":
59
+ name = (provider_name or self.default_provider()).lower()
60
+ if not name:
61
+ raise ValueError(
62
+ "Provider LLM no definido. Usa --provider, HIGPERTEXT_LLM_PROVIDER "
63
+ "o .higpertext/config/environment.json[llm.default_provider]."
64
+ )
65
+ if name in self._cache:
66
+ return self._cache[name]
67
+
68
+ if name not in _PROVIDER_MODULES:
69
+ raise ValueError(
70
+ f"Provider '{name}' no soportado. Disponibles: {list(_PROVIDER_MODULES)}"
71
+ )
72
+
73
+ module_path, class_name = _PROVIDER_MODULES[name]
74
+ import importlib
75
+
76
+ module = importlib.import_module(module_path)
77
+ provider_cls = getattr(module, class_name)
78
+ config = self.provider_config(name)
79
+ instance: "LLMProvider" = provider_cls(config=config)
80
+ self._cache[name] = instance
81
+ return instance