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,93 @@
1
+ """Casos de uso de perfiles y contexto de agente."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import asdict
6
+ from pathlib import Path
7
+
8
+ from higpertext.kernel.app_config import GLOBAL_PROFILE_NAMES
9
+ from higpertext.kernel.application.ports import (
10
+ ICapabilityRepository,
11
+ IProfileRepository,
12
+ IWorkflowRepository,
13
+ )
14
+ from higpertext.kernel.application.profile_service import ProfileService
15
+
16
+
17
+ class GetAgentContextUseCase:
18
+ """Construye el contexto activo para un perfil de agente."""
19
+
20
+ def __init__(
21
+ self,
22
+ profiles_repo: IProfileRepository,
23
+ caps_repo: ICapabilityRepository,
24
+ workflows_repo: IWorkflowRepository,
25
+ base_dir: Path,
26
+ ) -> None:
27
+ self.profiles_repo = profiles_repo
28
+ self.caps_repo = caps_repo
29
+ self.workflows_repo = workflows_repo
30
+ self.base_dir = base_dir
31
+
32
+ def execute(self, profile_name: str, env_data: dict | None = None) -> dict:
33
+ service = ProfileService(self.profiles_repo, self.caps_repo, self.base_dir)
34
+ profile = service.resolve_hierarchy(profile_name)
35
+ cap_ids = self._capability_ids_with_global_defaults(service, profile_name, profile.capabilities)
36
+
37
+ return {
38
+ "profile": asdict(profile),
39
+ "active_capabilities": self._load_capabilities(cap_ids),
40
+ "active_workflows": self._load_workflows(profile_name),
41
+ "environment": env_data or {},
42
+ }
43
+
44
+ def _capability_ids_with_global_defaults(
45
+ self, service: ProfileService, profile_name: str, capabilities: list[str]
46
+ ) -> list[str]:
47
+ cap_ids = list(capabilities)
48
+ if profile_name.lower() == "global":
49
+ return cap_ids
50
+
51
+ try:
52
+ global_profile = service.resolve_hierarchy("global")
53
+ for cap_id in global_profile.capabilities:
54
+ if cap_id not in cap_ids:
55
+ cap_ids.append(cap_id)
56
+ except (FileNotFoundError, ValueError): # nosec B110
57
+ pass
58
+ return cap_ids
59
+
60
+ def _load_capabilities(self, cap_ids: list[str]) -> list[dict]:
61
+ loaded_caps = []
62
+ for cap_id in cap_ids:
63
+ try:
64
+ loaded_caps.append(asdict(self.caps_repo.load(cap_id)))
65
+ except FileNotFoundError: # nosec B110
66
+ pass
67
+ return loaded_caps
68
+
69
+ def _load_workflows(self, profile_name: str) -> list[dict]:
70
+ profile_lower = profile_name.lower()
71
+ return [
72
+ asdict(workflow)
73
+ for workflow in self.workflows_repo.list_all()
74
+ if workflow.required_profile.lower() in GLOBAL_PROFILE_NAMES | {profile_lower}
75
+ ]
76
+
77
+
78
+ class ValidateProfileUseCase:
79
+ """Valida un perfil y sus dependencias declaradas."""
80
+
81
+ def __init__(
82
+ self,
83
+ profiles_repo: IProfileRepository,
84
+ caps_repo: ICapabilityRepository,
85
+ base_dir: Path,
86
+ ) -> None:
87
+ self.profiles_repo = profiles_repo
88
+ self.caps_repo = caps_repo
89
+ self.base_dir = base_dir
90
+
91
+ def execute(self, profile_name: str) -> tuple[bool, list[str], list[str]]:
92
+ service = ProfileService(self.profiles_repo, self.caps_repo, self.base_dir)
93
+ return service.validate_profile(profile_name)
@@ -0,0 +1,75 @@
1
+ """RAG Application Service - coordina la indexación y búsqueda semántica."""
2
+
3
+ from __future__ import annotations
4
+ from pathlib import Path
5
+ from higpertext.kernel.domain.rag import IEmbeddingProvider, IVectorStore, VectorEntry
6
+ from higpertext.kernel.infrastructure.parser.code_chunker import CodeChunker
7
+
8
+
9
+ class RAGService:
10
+ """Caso de uso orquestador de indexación y queries semánticas de RAG."""
11
+
12
+ def __init__(self, embedder: IEmbeddingProvider, store: IVectorStore) -> None:
13
+ self.embedder = embedder
14
+ self.store = store
15
+
16
+ def index_project(self, project_root: Path, file_globs: list[str] | None = None) -> int:
17
+ """Divide e indexa todos los archivos del proyecto que coincidan con los globs."""
18
+ if file_globs is None:
19
+ file_globs = ["src/**/*.py", "src/**/*.md", "tests/**/*.py"]
20
+
21
+ self.store.clear()
22
+ all_chunks = []
23
+
24
+ # Encontrar y parsear archivos
25
+ for glob_pattern in file_globs:
26
+ for file_path in project_root.glob(glob_pattern):
27
+ # Ignorar archivos en __pycache__ y .venv
28
+ if "__pycache__" in file_path.parts or ".venv" in file_path.parts or ".git" in file_path.parts:
29
+ continue
30
+ if file_path.is_file():
31
+ chunks = CodeChunker.chunk_file(file_path)
32
+ all_chunks.extend(chunks)
33
+
34
+ if not all_chunks:
35
+ return 0
36
+
37
+ # Generar embeddings e indexar
38
+ entries: list[VectorEntry] = []
39
+ for chunk in all_chunks:
40
+ try:
41
+ embedding = self.embedder.get_embedding(chunk.content)
42
+ entries.append(VectorEntry(chunk=chunk, embedding=embedding))
43
+ except Exception as e:
44
+ # Silenciar errores individuales de chunks de API para no romper la indexación global
45
+ print(f"[RAG WARNING] Falló generación de embedding para chunk en {chunk.file}: {e}")
46
+ continue
47
+
48
+ if entries:
49
+ self.store.add_entries(entries)
50
+ self.store.save()
51
+
52
+ return len(entries)
53
+
54
+ def search_context(self, query: str, limit: int = 5) -> list[dict]:
55
+ """Busca fragmentos semánticamente cercanos y los devuelve formateados."""
56
+ self.store.load()
57
+ try:
58
+ query_vector = self.embedder.get_embedding(query)
59
+ except Exception as e:
60
+ raise RuntimeError(f"Error al calcular embedding del query: {e}")
61
+
62
+ hits = self.store.search(query_vector, limit=limit)
63
+
64
+ serialized_hits = []
65
+ for chunk, score in hits:
66
+ serialized_hits.append({
67
+ "file": chunk.file,
68
+ "content": chunk.content,
69
+ "chunk_type": chunk.chunk_type,
70
+ "start_line": chunk.start_line,
71
+ "end_line": chunk.end_line,
72
+ "metadata": chunk.metadata,
73
+ "score": score
74
+ })
75
+ return serialized_hits
@@ -0,0 +1,178 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass, field
3
+ import json
4
+ from pathlib import Path
5
+
6
+ from higpertext.kernel.domain.roadmap_reporter import Phase, PhaseStatus, Roadmap, RoadmapReport
7
+ from higpertext.kernel.infrastructure.presentation.html_renderer import HtmlReportRenderer
8
+ from higpertext.kernel.infrastructure.presentation.markdown_report_renderer import MarkdownReportRenderer
9
+
10
+ _STATUS_ICON = {
11
+ PhaseStatus.DONE: "✅",
12
+ PhaseStatus.ACTIVE: "🔄",
13
+ PhaseStatus.PENDING: "⏳",
14
+ }
15
+ _STATUS_COLOR = {
16
+ PhaseStatus.DONE: "#3fb950",
17
+ PhaseStatus.ACTIVE: "#e3b341",
18
+ PhaseStatus.PENDING: "#8b949e",
19
+ }
20
+
21
+
22
+ @dataclass
23
+ class RoadmapAnalysis:
24
+ summary: str
25
+ completion_pct: float
26
+ impact_tags: list[str] = field(default_factory=list)
27
+ phase_insights: list[str] = field(default_factory=list)
28
+
29
+
30
+ class ProgressAnalyzer:
31
+ """Analiza un RoadmapReport y produce un resumen explicativo."""
32
+
33
+ def analyze(self, report: RoadmapReport) -> RoadmapAnalysis:
34
+ pct = report.completion_pct
35
+ active = report.active_phase
36
+ summary = self._build_summary(report, pct, active)
37
+ tags = self._build_tags(report, pct)
38
+ insights = self._build_insights(report)
39
+ return RoadmapAnalysis(
40
+ summary=summary,
41
+ completion_pct=pct,
42
+ impact_tags=tags,
43
+ phase_insights=insights,
44
+ )
45
+
46
+ def _build_summary(self, report, pct, active) -> str:
47
+ name = report.roadmap.name
48
+ done = report.done_phases
49
+ total = report.total_phases
50
+ if pct == 100.0:
51
+ return f'Roadmap "{name}" completed: all {total} phases done.'
52
+ active_part = f' Currently working on: "{active.name}".' if active else ""
53
+ return f'Roadmap "{name}" is {pct:.0f}% complete ({done}/{total} phases done).{active_part}'
54
+
55
+ def _build_tags(self, report, pct) -> list[str]:
56
+ tags = []
57
+ if pct == 100.0:
58
+ tags.append("completed")
59
+ elif report.active_phase:
60
+ tags.append("in-progress")
61
+ else:
62
+ tags.append("not-started")
63
+ if report.all_skills_used:
64
+ tags.append("skills-tracked")
65
+ if report.all_subagents_used:
66
+ tags.append("subagents-used")
67
+ return tags
68
+
69
+ def _build_insights(self, report) -> list[str]:
70
+ insights = []
71
+ for phase in report.roadmap.phases:
72
+ icon = _STATUS_ICON[phase.status]
73
+ skills_part = f", skills: {', '.join(phase.skills)}" if phase.skills else ""
74
+ insights.append(f"{icon} [{phase.status.value}] {phase.name}{skills_part}")
75
+ return insights
76
+
77
+
78
+ class RoadmapParser:
79
+ """Deserializa roadmap JSON en objetos de dominio."""
80
+
81
+ def parse(self, raw: str) -> RoadmapReport:
82
+ try:
83
+ data = json.loads(raw)
84
+ except json.JSONDecodeError as exc:
85
+ raise ValueError(f"Invalid roadmap JSON: {exc}") from exc
86
+ return self._build_report(data)
87
+
88
+ def parse_file(self, path: Path) -> RoadmapReport:
89
+ return self.parse(path.read_text(encoding="utf-8"))
90
+
91
+ def _build_report(self, data: dict) -> RoadmapReport:
92
+ phases = [self._build_phase(p) for p in data.get("phases", [])]
93
+ roadmap = Roadmap(
94
+ id=data["id"],
95
+ name=data["name"],
96
+ description=data.get("description", ""),
97
+ phases=phases,
98
+ )
99
+ return RoadmapReport(roadmap=roadmap)
100
+
101
+ def _build_phase(self, data: dict) -> Phase:
102
+ return Phase(
103
+ id=data["id"],
104
+ name=data["name"],
105
+ description=data.get("description", ""),
106
+ status=PhaseStatus(data.get("status", "pending")),
107
+ skills=list(data.get("skills", [])),
108
+ subagents=list(data.get("subagents", [])),
109
+ )
110
+
111
+
112
+ class RoadmapReportBuilder:
113
+ """Genera reportes Markdown y HTML para un RoadmapReport."""
114
+
115
+ def to_markdown(self, report: RoadmapReport, analysis: RoadmapAnalysis) -> str:
116
+ r = report.roadmap
117
+ renderer = MarkdownReportRenderer()
118
+ tags = " ".join(f"`{t}`" for t in analysis.impact_tags)
119
+ phases_rows = "\n".join(
120
+ f"| {i} | {phase.name} | {_STATUS_ICON[phase.status]} {phase.status.value}"
121
+ f" | {", ".join(phase.skills) or '—'} | {", ".join(phase.subagents) or '—'} |"
122
+ for i, phase in enumerate(r.phases, 1)
123
+ )
124
+ insights = "\n".join(f"- {ins}" for ins in analysis.phase_insights)
125
+ return renderer.render_roadmap_report(
126
+ name=r.name,
127
+ summary=analysis.summary,
128
+ completion_pct=f"{analysis.completion_pct:.0f}",
129
+ done_phases=report.done_phases,
130
+ total_phases=report.total_phases,
131
+ tags=tags,
132
+ phases_rows=phases_rows,
133
+ insights=insights,
134
+ skills_all=", ".join(report.all_skills_used) or "—",
135
+ subs_all=", ".join(report.all_subagents_used) or "—",
136
+ )
137
+
138
+ def to_html(self, report: RoadmapReport, analysis: RoadmapAnalysis) -> str:
139
+ renderer = HtmlReportRenderer()
140
+ r = report.roadmap
141
+ pct = f"{analysis.completion_pct:.0f}"
142
+ tags_html = " ".join(
143
+ f'<span class="tag">{t}</span>' for t in analysis.impact_tags
144
+ )
145
+ phases_html = "\n".join(
146
+ renderer.render_roadmap_phase(
147
+ css=f"phase-{p.status.value}",
148
+ icon=_STATUS_ICON[p.status],
149
+ name=p.name,
150
+ status=p.status.value,
151
+ description=p.description or "",
152
+ skills_html=" ".join(
153
+ f'<span class="skill-tag">{s}</span>' for s in p.skills
154
+ ),
155
+ subs_html=" ".join(
156
+ f'<span class="sub-tag">{a}</span>' for a in p.subagents
157
+ ),
158
+ )
159
+ for p in r.phases
160
+ )
161
+ skills_html = " ".join(
162
+ f'<span class="skill-tag">{s}</span>' for s in report.all_skills_used
163
+ ) or "—"
164
+ subs_html = " ".join(
165
+ f'<span class="sub-tag">{a}</span>' for a in report.all_subagents_used
166
+ ) or "—"
167
+ body = renderer.render_roadmap_body(
168
+ name=r.name,
169
+ done_phases=report.done_phases,
170
+ total_phases=report.total_phases,
171
+ summary=analysis.summary,
172
+ tags_html=tags_html,
173
+ pct=pct,
174
+ phases_html=phases_html,
175
+ skills_html=skills_html,
176
+ subs_html=subs_html,
177
+ )
178
+ return renderer.render_roadmap_shell(title=r.name, body=body)
@@ -0,0 +1,258 @@
1
+ """Semantic Engine Application layer — ClusterService, ContextRanker, and GraphBuilder."""
2
+
3
+ from __future__ import annotations
4
+ import json
5
+ from collections import defaultdict, deque
6
+ from pathlib import Path
7
+ from higpertext.kernel.domain.semantic_engine import Cluster, SemanticGraph, Symbol, Relation
8
+ from higpertext.kernel.config_paths import PROJECT_ROOT
9
+
10
+ _SG_CONFIG_PATH = PROJECT_ROOT / "src" / "config" / "semantic_graph.json"
11
+ _SG: dict = json.loads(_SG_CONFIG_PATH.read_text(encoding="utf-8"))
12
+ _SCORES: dict = _SG["ranking"]["scores"]
13
+ _BASE_TOKENS_PER_SYMBOL: int = _SG["ranking"]["base_tokens_per_symbol"]
14
+ _IGNORE_FOLDERS: frozenset[str] = frozenset(_SG["ignore_folders"])
15
+
16
+
17
+ class ClusterService:
18
+ """Detecta comunidades usando Louvain phase-1 (modularity gain greedy)."""
19
+
20
+ def detect(self, graph: SemanticGraph, max_passes: int = 20) -> list[Cluster]:
21
+ symbols = graph.all_symbols()
22
+ if not symbols:
23
+ return []
24
+
25
+ fqns = [s.fqn for s in symbols]
26
+ sym_by_fqn: dict[str, Symbol] = {s.fqn: s for s in symbols}
27
+
28
+ # Adyacencia ponderada (peso = número de aristas entre par)
29
+ adj: dict[str, dict[str, float]] = defaultdict(lambda: defaultdict(float))
30
+ total_weight = 0.0
31
+ for rel in graph.all_relations():
32
+ adj[rel.source.fqn][rel.target.fqn] += 1.0
33
+ adj[rel.target.fqn][rel.source.fqn] += 1.0
34
+ total_weight += 1.0
35
+ m = total_weight or 1.0
36
+
37
+ # Grado de cada nodo
38
+ degree: dict[str, float] = {fqn: sum(adj[fqn].values()) for fqn in fqns}
39
+
40
+ # Comunidad inicial: cada nodo es su propia comunidad
41
+ community: dict[str, int] = {fqn: i for i, fqn in enumerate(fqns)}
42
+
43
+ def _modularity_gain(fqn: str, target_comm: int) -> float:
44
+ k_i = degree[fqn]
45
+ k_i_in = sum(w for nb, w in adj[fqn].items() if community[nb] == target_comm)
46
+ sigma_tot = sum(degree[f] for f in fqns if community[f] == target_comm)
47
+ return (k_i_in / m) - (sigma_tot * k_i) / (2 * m * m)
48
+
49
+ for _ in range(max_passes):
50
+ moved = False
51
+ for fqn in fqns:
52
+ current = community[fqn]
53
+ best_comm = current
54
+ best_gain = 0.0
55
+
56
+ neighbors_comms = {community[nb] for nb in adj[fqn]}
57
+ neighbors_comms.discard(current)
58
+
59
+ for candidate in neighbors_comms:
60
+ gain = _modularity_gain(fqn, candidate) - _modularity_gain(fqn, current)
61
+ if gain > best_gain:
62
+ best_gain = gain
63
+ best_comm = candidate
64
+
65
+ if best_comm != current:
66
+ community[fqn] = best_comm
67
+ moved = True
68
+
69
+ if not moved:
70
+ break
71
+
72
+ # Renumera comunidades de forma compacta
73
+ label_map: dict[int, int] = {}
74
+ counter = 0
75
+ for old in community.values():
76
+ if old not in label_map:
77
+ label_map[old] = counter
78
+ counter += 1
79
+
80
+ groups: dict[int, list[Symbol]] = defaultdict(list)
81
+ for fqn, comm in community.items():
82
+ groups[label_map[comm]].append(sym_by_fqn[fqn])
83
+
84
+ return [
85
+ Cluster(id=f"cluster-{cid}", members=members) for cid, members in sorted(groups.items())
86
+ ]
87
+
88
+
89
+ class ContextRanker:
90
+ """Rankea símbolos del grafo por relevancia a un conjunto de keywords."""
91
+
92
+ def __init__(self, graph: SemanticGraph) -> None:
93
+ self._graph = graph
94
+ self._in_degree = self._build_in_degree()
95
+
96
+ def _build_in_degree(self) -> dict[str, int]:
97
+ degree: dict[str, int] = {}
98
+ for rel in self._graph.all_relations():
99
+ degree[rel.target.fqn] = degree.get(rel.target.fqn, 0) + 1
100
+ return degree
101
+
102
+ @staticmethod
103
+ def _symbol_text(symbol: Symbol) -> str:
104
+ return " ".join((symbol.name, symbol.fqn, symbol.file, symbol.type.value)).lower()
105
+
106
+ def _match_score(self, symbol: Symbol, keywords: list[str]) -> int:
107
+ score = 0
108
+ name = symbol.name.lower()
109
+ file = symbol.file.lower()
110
+ fqn = symbol.fqn.lower()
111
+ symbol_type = symbol.type.value.lower()
112
+ for kw in keywords:
113
+ structural_query = any(mark in kw for mark in ("/", ".", "::"))
114
+ if kw == name:
115
+ score += _SCORES["exact_name"]
116
+ elif name.startswith(kw):
117
+ score += _SCORES["name_starts_with"]
118
+ elif kw in name:
119
+ score += _SCORES["name_contains"]
120
+ if structural_query and kw in fqn:
121
+ score += _SCORES["structural_fqn"]
122
+ if structural_query and kw in file:
123
+ score += _SCORES["structural_file"]
124
+ if kw == symbol_type:
125
+ score += _SCORES["type_match"]
126
+ return score
127
+
128
+ @staticmethod
129
+ def _token_cost(symbol: Symbol) -> int:
130
+ return _BASE_TOKENS_PER_SYMBOL + max(1, (len(symbol.fqn) + len(symbol.type.value)) // 4)
131
+
132
+ def rank(
133
+ self,
134
+ keywords: list[str],
135
+ budget: int,
136
+ depth: int = 2,
137
+ ) -> list[Symbol]:
138
+ if not keywords or budget <= 0:
139
+ return []
140
+
141
+ lower_kws = [kw.lower() for kw in keywords]
142
+ all_symbols = self._graph.all_symbols()
143
+
144
+ seeds = [s for s in all_symbols if self._match_score(s, lower_kws) > 0]
145
+ if not seeds:
146
+ return []
147
+
148
+ seeds.sort(
149
+ key=lambda s: (
150
+ -self._match_score(s, lower_kws),
151
+ -self._in_degree.get(s.fqn, 0),
152
+ s.file,
153
+ s.name,
154
+ ),
155
+ )
156
+
157
+ visited: dict[str, Symbol] = {}
158
+ queue: deque[tuple[Symbol, int]] = deque()
159
+
160
+ for seed in seeds:
161
+ if seed.fqn not in visited:
162
+ visited[seed.fqn] = seed
163
+ queue.append((seed, 0))
164
+
165
+ while queue:
166
+ sym, current_depth = queue.popleft()
167
+ if current_depth >= depth:
168
+ continue
169
+ for neighbor in self._graph.neighbors(sym):
170
+ if neighbor.fqn not in visited:
171
+ visited[neighbor.fqn] = neighbor
172
+ queue.append((neighbor, current_depth + 1))
173
+
174
+ seed_fqns = {s.fqn for s in seeds}
175
+ ordered = sorted(
176
+ visited.values(),
177
+ key=lambda s: (
178
+ 0 if s.fqn in seed_fqns else 1,
179
+ -self._match_score(s, lower_kws),
180
+ -self._in_degree.get(s.fqn, 0),
181
+ s.file,
182
+ s.name,
183
+ ),
184
+ )
185
+
186
+ result: list[Symbol] = []
187
+ tokens_used = 0
188
+ for sym in ordered:
189
+ cost = self._token_cost(sym)
190
+ if tokens_used + cost > budget:
191
+ break
192
+ result.append(sym)
193
+ tokens_used += cost
194
+
195
+ return result
196
+
197
+
198
+ class GraphBuilder:
199
+ """Orquesta parsers multi-lenguaje y construye el SemanticGraph con caché incremental."""
200
+
201
+ def build(self, root: Path, incremental: bool = True) -> SemanticGraph:
202
+ return self.build_with_stats(root, incremental)["graph"]
203
+
204
+ def build_with_stats(self, root: Path, incremental: bool = True) -> dict:
205
+ from higpertext.kernel.infrastructure.semantic_engine import (
206
+ FileCache,
207
+ PythonParser,
208
+ TypeScriptParser,
209
+ LanguageParser,
210
+ )
211
+ from higpertext.kernel.config_paths import WORKSPACE_DIR_NAME
212
+
213
+ _ignore = _IGNORE_FOLDERS | {WORKSPACE_DIR_NAME}
214
+
215
+ parsers: dict[str, LanguageParser] = {
216
+ ext: _PARSER_CLASS()
217
+ for ext, _PARSER_CLASS in (
218
+ (".py", PythonParser),
219
+ (".ts", TypeScriptParser),
220
+ (".tsx", TypeScriptParser),
221
+ (".js", TypeScriptParser),
222
+ (".jsx", TypeScriptParser),
223
+ )
224
+ }
225
+
226
+ cache = FileCache(root)
227
+ cached_hashes = cache.load() if incremental else {}
228
+ new_hashes: dict[str, str] = dict(cached_hashes)
229
+ graph = SemanticGraph()
230
+ parsed = 0
231
+ skipped = 0
232
+
233
+ # Iterar archivos
234
+ for file_path in root.rglob("*"):
235
+ if file_path.suffix not in parsers:
236
+ continue
237
+ if any(part in _ignore for part in file_path.parts):
238
+ continue
239
+
240
+ rel = file_path.relative_to(root).as_posix()
241
+ cached = cached_hashes.get(rel)
242
+ if incremental and not cache.is_changed(rel, file_path, cached):
243
+ skipped += 1
244
+ continue
245
+
246
+ parser = parsers[file_path.suffix]
247
+ source = file_path.read_text(encoding="utf-8", errors="ignore")
248
+ symbols, relations = parser.parse(source=source, file=rel)
249
+ for sym in symbols:
250
+ graph.add_symbol(sym)
251
+ for rel_obj in relations:
252
+ graph.add_relation(rel_obj)
253
+ new_hashes[rel] = cache.compute(file_path)
254
+ parsed += 1
255
+
256
+ if incremental:
257
+ cache.save(new_hashes)
258
+ return {"graph": graph, "parsed": parsed, "skipped": skipped}
@@ -0,0 +1,33 @@
1
+ """Lógica pura de aplicación para gestión de ciclo de vida de Sesión."""
2
+
3
+ from __future__ import annotations
4
+ import datetime
5
+ import secrets
6
+ from higpertext.kernel.domain.entities import Session
7
+ from higpertext.kernel.application.ports import ISessionRepository, IProfileRepository
8
+
9
+
10
+ class SessionApplicationService:
11
+ def __init__(self, session_repo: ISessionRepository, profile_repo: IProfileRepository):
12
+ self.session_repo = session_repo
13
+ self.profile_repo = profile_repo
14
+
15
+ def create_session(
16
+ self, profile_name: str, assistant: str, skills: list[str], subagents: list[str]
17
+ ) -> Session:
18
+ session_id = f"sess_{int(datetime.datetime.now().timestamp())}_{secrets.token_hex(2)}"
19
+ new_session = Session(
20
+ session_id=session_id,
21
+ profile=profile_name,
22
+ assistant=assistant,
23
+ status="active",
24
+ created_at=datetime.datetime.now().isoformat(),
25
+ active_skills=skills,
26
+ active_subagents=subagents,
27
+ tasks=[],
28
+ )
29
+ self.session_repo.save(new_session)
30
+ return new_session
31
+
32
+ def clean_session(self) -> None:
33
+ self.session_repo.delete()