attune-ai 2.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.
Files changed (457) hide show
  1. attune/__init__.py +358 -0
  2. attune/adaptive/__init__.py +13 -0
  3. attune/adaptive/task_complexity.py +127 -0
  4. attune/agent_monitoring.py +414 -0
  5. attune/cache/__init__.py +117 -0
  6. attune/cache/base.py +166 -0
  7. attune/cache/dependency_manager.py +256 -0
  8. attune/cache/hash_only.py +251 -0
  9. attune/cache/hybrid.py +457 -0
  10. attune/cache/storage.py +285 -0
  11. attune/cache_monitor.py +356 -0
  12. attune/cache_stats.py +298 -0
  13. attune/cli/__init__.py +152 -0
  14. attune/cli/__main__.py +12 -0
  15. attune/cli/commands/__init__.py +1 -0
  16. attune/cli/commands/batch.py +264 -0
  17. attune/cli/commands/cache.py +248 -0
  18. attune/cli/commands/help.py +331 -0
  19. attune/cli/commands/info.py +140 -0
  20. attune/cli/commands/inspect.py +436 -0
  21. attune/cli/commands/inspection.py +57 -0
  22. attune/cli/commands/memory.py +48 -0
  23. attune/cli/commands/metrics.py +92 -0
  24. attune/cli/commands/orchestrate.py +184 -0
  25. attune/cli/commands/patterns.py +207 -0
  26. attune/cli/commands/profiling.py +202 -0
  27. attune/cli/commands/provider.py +98 -0
  28. attune/cli/commands/routing.py +285 -0
  29. attune/cli/commands/setup.py +96 -0
  30. attune/cli/commands/status.py +235 -0
  31. attune/cli/commands/sync.py +166 -0
  32. attune/cli/commands/tier.py +121 -0
  33. attune/cli/commands/utilities.py +114 -0
  34. attune/cli/commands/workflow.py +579 -0
  35. attune/cli/core.py +32 -0
  36. attune/cli/parsers/__init__.py +68 -0
  37. attune/cli/parsers/batch.py +118 -0
  38. attune/cli/parsers/cache.py +65 -0
  39. attune/cli/parsers/help.py +41 -0
  40. attune/cli/parsers/info.py +26 -0
  41. attune/cli/parsers/inspect.py +66 -0
  42. attune/cli/parsers/metrics.py +42 -0
  43. attune/cli/parsers/orchestrate.py +61 -0
  44. attune/cli/parsers/patterns.py +54 -0
  45. attune/cli/parsers/provider.py +40 -0
  46. attune/cli/parsers/routing.py +110 -0
  47. attune/cli/parsers/setup.py +42 -0
  48. attune/cli/parsers/status.py +47 -0
  49. attune/cli/parsers/sync.py +31 -0
  50. attune/cli/parsers/tier.py +33 -0
  51. attune/cli/parsers/workflow.py +77 -0
  52. attune/cli/utils/__init__.py +1 -0
  53. attune/cli/utils/data.py +242 -0
  54. attune/cli/utils/helpers.py +68 -0
  55. attune/cli_legacy.py +3957 -0
  56. attune/cli_minimal.py +1159 -0
  57. attune/cli_router.py +437 -0
  58. attune/cli_unified.py +814 -0
  59. attune/config/__init__.py +66 -0
  60. attune/config/xml_config.py +286 -0
  61. attune/config.py +545 -0
  62. attune/coordination.py +870 -0
  63. attune/core.py +1511 -0
  64. attune/core_modules/__init__.py +15 -0
  65. attune/cost_tracker.py +626 -0
  66. attune/dashboard/__init__.py +41 -0
  67. attune/dashboard/app.py +512 -0
  68. attune/dashboard/simple_server.py +435 -0
  69. attune/dashboard/standalone_server.py +547 -0
  70. attune/discovery.py +306 -0
  71. attune/emergence.py +306 -0
  72. attune/exceptions.py +123 -0
  73. attune/feedback_loops.py +373 -0
  74. attune/hot_reload/README.md +473 -0
  75. attune/hot_reload/__init__.py +62 -0
  76. attune/hot_reload/config.py +83 -0
  77. attune/hot_reload/integration.py +229 -0
  78. attune/hot_reload/reloader.py +298 -0
  79. attune/hot_reload/watcher.py +183 -0
  80. attune/hot_reload/websocket.py +177 -0
  81. attune/levels.py +577 -0
  82. attune/leverage_points.py +441 -0
  83. attune/logging_config.py +261 -0
  84. attune/mcp/__init__.py +10 -0
  85. attune/mcp/server.py +506 -0
  86. attune/memory/__init__.py +237 -0
  87. attune/memory/claude_memory.py +469 -0
  88. attune/memory/config.py +224 -0
  89. attune/memory/control_panel.py +1290 -0
  90. attune/memory/control_panel_support.py +145 -0
  91. attune/memory/cross_session.py +845 -0
  92. attune/memory/edges.py +179 -0
  93. attune/memory/encryption.py +159 -0
  94. attune/memory/file_session.py +770 -0
  95. attune/memory/graph.py +570 -0
  96. attune/memory/long_term.py +913 -0
  97. attune/memory/long_term_types.py +99 -0
  98. attune/memory/mixins/__init__.py +25 -0
  99. attune/memory/mixins/backend_init_mixin.py +249 -0
  100. attune/memory/mixins/capabilities_mixin.py +208 -0
  101. attune/memory/mixins/handoff_mixin.py +208 -0
  102. attune/memory/mixins/lifecycle_mixin.py +49 -0
  103. attune/memory/mixins/long_term_mixin.py +352 -0
  104. attune/memory/mixins/promotion_mixin.py +109 -0
  105. attune/memory/mixins/short_term_mixin.py +182 -0
  106. attune/memory/nodes.py +179 -0
  107. attune/memory/redis_bootstrap.py +540 -0
  108. attune/memory/security/__init__.py +31 -0
  109. attune/memory/security/audit_logger.py +932 -0
  110. attune/memory/security/pii_scrubber.py +640 -0
  111. attune/memory/security/secrets_detector.py +678 -0
  112. attune/memory/short_term.py +2192 -0
  113. attune/memory/simple_storage.py +302 -0
  114. attune/memory/storage/__init__.py +15 -0
  115. attune/memory/storage_backend.py +167 -0
  116. attune/memory/summary_index.py +583 -0
  117. attune/memory/types.py +446 -0
  118. attune/memory/unified.py +182 -0
  119. attune/meta_workflows/__init__.py +74 -0
  120. attune/meta_workflows/agent_creator.py +248 -0
  121. attune/meta_workflows/builtin_templates.py +567 -0
  122. attune/meta_workflows/cli_commands/__init__.py +56 -0
  123. attune/meta_workflows/cli_commands/agent_commands.py +321 -0
  124. attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
  125. attune/meta_workflows/cli_commands/config_commands.py +232 -0
  126. attune/meta_workflows/cli_commands/memory_commands.py +182 -0
  127. attune/meta_workflows/cli_commands/template_commands.py +354 -0
  128. attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
  129. attune/meta_workflows/cli_meta_workflows.py +59 -0
  130. attune/meta_workflows/form_engine.py +292 -0
  131. attune/meta_workflows/intent_detector.py +409 -0
  132. attune/meta_workflows/models.py +569 -0
  133. attune/meta_workflows/pattern_learner.py +738 -0
  134. attune/meta_workflows/plan_generator.py +384 -0
  135. attune/meta_workflows/session_context.py +397 -0
  136. attune/meta_workflows/template_registry.py +229 -0
  137. attune/meta_workflows/workflow.py +984 -0
  138. attune/metrics/__init__.py +12 -0
  139. attune/metrics/collector.py +31 -0
  140. attune/metrics/prompt_metrics.py +194 -0
  141. attune/models/__init__.py +172 -0
  142. attune/models/__main__.py +13 -0
  143. attune/models/adaptive_routing.py +437 -0
  144. attune/models/auth_cli.py +444 -0
  145. attune/models/auth_strategy.py +450 -0
  146. attune/models/cli.py +655 -0
  147. attune/models/empathy_executor.py +354 -0
  148. attune/models/executor.py +257 -0
  149. attune/models/fallback.py +762 -0
  150. attune/models/provider_config.py +282 -0
  151. attune/models/registry.py +472 -0
  152. attune/models/tasks.py +359 -0
  153. attune/models/telemetry/__init__.py +71 -0
  154. attune/models/telemetry/analytics.py +594 -0
  155. attune/models/telemetry/backend.py +196 -0
  156. attune/models/telemetry/data_models.py +431 -0
  157. attune/models/telemetry/storage.py +489 -0
  158. attune/models/token_estimator.py +420 -0
  159. attune/models/validation.py +280 -0
  160. attune/monitoring/__init__.py +52 -0
  161. attune/monitoring/alerts.py +946 -0
  162. attune/monitoring/alerts_cli.py +448 -0
  163. attune/monitoring/multi_backend.py +271 -0
  164. attune/monitoring/otel_backend.py +362 -0
  165. attune/optimization/__init__.py +19 -0
  166. attune/optimization/context_optimizer.py +272 -0
  167. attune/orchestration/__init__.py +67 -0
  168. attune/orchestration/agent_templates.py +707 -0
  169. attune/orchestration/config_store.py +499 -0
  170. attune/orchestration/execution_strategies.py +2111 -0
  171. attune/orchestration/meta_orchestrator.py +1168 -0
  172. attune/orchestration/pattern_learner.py +696 -0
  173. attune/orchestration/real_tools.py +931 -0
  174. attune/pattern_cache.py +187 -0
  175. attune/pattern_library.py +542 -0
  176. attune/patterns/debugging/all_patterns.json +81 -0
  177. attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
  178. attune/patterns/refactoring_memory.json +89 -0
  179. attune/persistence.py +564 -0
  180. attune/platform_utils.py +265 -0
  181. attune/plugins/__init__.py +28 -0
  182. attune/plugins/base.py +361 -0
  183. attune/plugins/registry.py +268 -0
  184. attune/project_index/__init__.py +32 -0
  185. attune/project_index/cli.py +335 -0
  186. attune/project_index/index.py +667 -0
  187. attune/project_index/models.py +504 -0
  188. attune/project_index/reports.py +474 -0
  189. attune/project_index/scanner.py +777 -0
  190. attune/project_index/scanner_parallel.py +291 -0
  191. attune/prompts/__init__.py +61 -0
  192. attune/prompts/config.py +77 -0
  193. attune/prompts/context.py +177 -0
  194. attune/prompts/parser.py +285 -0
  195. attune/prompts/registry.py +313 -0
  196. attune/prompts/templates.py +208 -0
  197. attune/redis_config.py +302 -0
  198. attune/redis_memory.py +799 -0
  199. attune/resilience/__init__.py +56 -0
  200. attune/resilience/circuit_breaker.py +256 -0
  201. attune/resilience/fallback.py +179 -0
  202. attune/resilience/health.py +300 -0
  203. attune/resilience/retry.py +209 -0
  204. attune/resilience/timeout.py +135 -0
  205. attune/routing/__init__.py +43 -0
  206. attune/routing/chain_executor.py +433 -0
  207. attune/routing/classifier.py +217 -0
  208. attune/routing/smart_router.py +234 -0
  209. attune/routing/workflow_registry.py +343 -0
  210. attune/scaffolding/README.md +589 -0
  211. attune/scaffolding/__init__.py +35 -0
  212. attune/scaffolding/__main__.py +14 -0
  213. attune/scaffolding/cli.py +240 -0
  214. attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
  215. attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
  216. attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
  217. attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
  218. attune/socratic/__init__.py +256 -0
  219. attune/socratic/ab_testing.py +958 -0
  220. attune/socratic/blueprint.py +533 -0
  221. attune/socratic/cli.py +703 -0
  222. attune/socratic/collaboration.py +1114 -0
  223. attune/socratic/domain_templates.py +924 -0
  224. attune/socratic/embeddings.py +738 -0
  225. attune/socratic/engine.py +794 -0
  226. attune/socratic/explainer.py +682 -0
  227. attune/socratic/feedback.py +772 -0
  228. attune/socratic/forms.py +629 -0
  229. attune/socratic/generator.py +732 -0
  230. attune/socratic/llm_analyzer.py +637 -0
  231. attune/socratic/mcp_server.py +702 -0
  232. attune/socratic/session.py +312 -0
  233. attune/socratic/storage.py +667 -0
  234. attune/socratic/success.py +730 -0
  235. attune/socratic/visual_editor.py +860 -0
  236. attune/socratic/web_ui.py +958 -0
  237. attune/telemetry/__init__.py +39 -0
  238. attune/telemetry/agent_coordination.py +475 -0
  239. attune/telemetry/agent_tracking.py +367 -0
  240. attune/telemetry/approval_gates.py +545 -0
  241. attune/telemetry/cli.py +1231 -0
  242. attune/telemetry/commands/__init__.py +14 -0
  243. attune/telemetry/commands/dashboard_commands.py +696 -0
  244. attune/telemetry/event_streaming.py +409 -0
  245. attune/telemetry/feedback_loop.py +567 -0
  246. attune/telemetry/usage_tracker.py +591 -0
  247. attune/templates.py +754 -0
  248. attune/test_generator/__init__.py +38 -0
  249. attune/test_generator/__main__.py +14 -0
  250. attune/test_generator/cli.py +234 -0
  251. attune/test_generator/generator.py +355 -0
  252. attune/test_generator/risk_analyzer.py +216 -0
  253. attune/test_generator/templates/unit_test.py.jinja2 +272 -0
  254. attune/tier_recommender.py +384 -0
  255. attune/tools.py +183 -0
  256. attune/trust/__init__.py +28 -0
  257. attune/trust/circuit_breaker.py +579 -0
  258. attune/trust_building.py +527 -0
  259. attune/validation/__init__.py +19 -0
  260. attune/validation/xml_validator.py +281 -0
  261. attune/vscode_bridge.py +173 -0
  262. attune/workflow_commands.py +780 -0
  263. attune/workflow_patterns/__init__.py +33 -0
  264. attune/workflow_patterns/behavior.py +249 -0
  265. attune/workflow_patterns/core.py +76 -0
  266. attune/workflow_patterns/output.py +99 -0
  267. attune/workflow_patterns/registry.py +255 -0
  268. attune/workflow_patterns/structural.py +288 -0
  269. attune/workflows/__init__.py +539 -0
  270. attune/workflows/autonomous_test_gen.py +1268 -0
  271. attune/workflows/base.py +2667 -0
  272. attune/workflows/batch_processing.py +342 -0
  273. attune/workflows/bug_predict.py +1084 -0
  274. attune/workflows/builder.py +273 -0
  275. attune/workflows/caching.py +253 -0
  276. attune/workflows/code_review.py +1048 -0
  277. attune/workflows/code_review_adapters.py +312 -0
  278. attune/workflows/code_review_pipeline.py +722 -0
  279. attune/workflows/config.py +645 -0
  280. attune/workflows/dependency_check.py +644 -0
  281. attune/workflows/document_gen/__init__.py +25 -0
  282. attune/workflows/document_gen/config.py +30 -0
  283. attune/workflows/document_gen/report_formatter.py +162 -0
  284. attune/workflows/document_gen/workflow.py +1426 -0
  285. attune/workflows/document_manager.py +216 -0
  286. attune/workflows/document_manager_README.md +134 -0
  287. attune/workflows/documentation_orchestrator.py +1205 -0
  288. attune/workflows/history.py +510 -0
  289. attune/workflows/keyboard_shortcuts/__init__.py +39 -0
  290. attune/workflows/keyboard_shortcuts/generators.py +391 -0
  291. attune/workflows/keyboard_shortcuts/parsers.py +416 -0
  292. attune/workflows/keyboard_shortcuts/prompts.py +295 -0
  293. attune/workflows/keyboard_shortcuts/schema.py +193 -0
  294. attune/workflows/keyboard_shortcuts/workflow.py +509 -0
  295. attune/workflows/llm_base.py +363 -0
  296. attune/workflows/manage_docs.py +87 -0
  297. attune/workflows/manage_docs_README.md +134 -0
  298. attune/workflows/manage_documentation.py +821 -0
  299. attune/workflows/new_sample_workflow1.py +149 -0
  300. attune/workflows/new_sample_workflow1_README.md +150 -0
  301. attune/workflows/orchestrated_health_check.py +849 -0
  302. attune/workflows/orchestrated_release_prep.py +600 -0
  303. attune/workflows/output.py +413 -0
  304. attune/workflows/perf_audit.py +863 -0
  305. attune/workflows/pr_review.py +762 -0
  306. attune/workflows/progress.py +785 -0
  307. attune/workflows/progress_server.py +322 -0
  308. attune/workflows/progressive/README 2.md +454 -0
  309. attune/workflows/progressive/README.md +454 -0
  310. attune/workflows/progressive/__init__.py +82 -0
  311. attune/workflows/progressive/cli.py +219 -0
  312. attune/workflows/progressive/core.py +488 -0
  313. attune/workflows/progressive/orchestrator.py +723 -0
  314. attune/workflows/progressive/reports.py +520 -0
  315. attune/workflows/progressive/telemetry.py +274 -0
  316. attune/workflows/progressive/test_gen.py +495 -0
  317. attune/workflows/progressive/workflow.py +589 -0
  318. attune/workflows/refactor_plan.py +694 -0
  319. attune/workflows/release_prep.py +895 -0
  320. attune/workflows/release_prep_crew.py +969 -0
  321. attune/workflows/research_synthesis.py +404 -0
  322. attune/workflows/routing.py +168 -0
  323. attune/workflows/secure_release.py +593 -0
  324. attune/workflows/security_adapters.py +297 -0
  325. attune/workflows/security_audit.py +1329 -0
  326. attune/workflows/security_audit_phase3.py +355 -0
  327. attune/workflows/seo_optimization.py +633 -0
  328. attune/workflows/step_config.py +234 -0
  329. attune/workflows/telemetry_mixin.py +269 -0
  330. attune/workflows/test5.py +125 -0
  331. attune/workflows/test5_README.md +158 -0
  332. attune/workflows/test_coverage_boost_crew.py +849 -0
  333. attune/workflows/test_gen/__init__.py +52 -0
  334. attune/workflows/test_gen/ast_analyzer.py +249 -0
  335. attune/workflows/test_gen/config.py +88 -0
  336. attune/workflows/test_gen/data_models.py +38 -0
  337. attune/workflows/test_gen/report_formatter.py +289 -0
  338. attune/workflows/test_gen/test_templates.py +381 -0
  339. attune/workflows/test_gen/workflow.py +655 -0
  340. attune/workflows/test_gen.py +54 -0
  341. attune/workflows/test_gen_behavioral.py +477 -0
  342. attune/workflows/test_gen_parallel.py +341 -0
  343. attune/workflows/test_lifecycle.py +526 -0
  344. attune/workflows/test_maintenance.py +627 -0
  345. attune/workflows/test_maintenance_cli.py +590 -0
  346. attune/workflows/test_maintenance_crew.py +840 -0
  347. attune/workflows/test_runner.py +622 -0
  348. attune/workflows/tier_tracking.py +531 -0
  349. attune/workflows/xml_enhanced_crew.py +285 -0
  350. attune_ai-2.0.0.dist-info/METADATA +1026 -0
  351. attune_ai-2.0.0.dist-info/RECORD +457 -0
  352. attune_ai-2.0.0.dist-info/WHEEL +5 -0
  353. attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
  354. attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
  355. attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
  356. attune_ai-2.0.0.dist-info/top_level.txt +5 -0
  357. attune_healthcare/__init__.py +13 -0
  358. attune_healthcare/monitors/__init__.py +9 -0
  359. attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
  360. attune_healthcare/monitors/monitoring/__init__.py +44 -0
  361. attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
  362. attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
  363. attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
  364. attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
  365. attune_llm/README.md +553 -0
  366. attune_llm/__init__.py +28 -0
  367. attune_llm/agent_factory/__init__.py +53 -0
  368. attune_llm/agent_factory/adapters/__init__.py +85 -0
  369. attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
  370. attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
  371. attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
  372. attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
  373. attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
  374. attune_llm/agent_factory/adapters/native.py +228 -0
  375. attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
  376. attune_llm/agent_factory/base.py +305 -0
  377. attune_llm/agent_factory/crews/__init__.py +67 -0
  378. attune_llm/agent_factory/crews/code_review.py +1113 -0
  379. attune_llm/agent_factory/crews/health_check.py +1262 -0
  380. attune_llm/agent_factory/crews/refactoring.py +1128 -0
  381. attune_llm/agent_factory/crews/security_audit.py +1018 -0
  382. attune_llm/agent_factory/decorators.py +287 -0
  383. attune_llm/agent_factory/factory.py +558 -0
  384. attune_llm/agent_factory/framework.py +193 -0
  385. attune_llm/agent_factory/memory_integration.py +328 -0
  386. attune_llm/agent_factory/resilient.py +320 -0
  387. attune_llm/agents_md/__init__.py +22 -0
  388. attune_llm/agents_md/loader.py +218 -0
  389. attune_llm/agents_md/parser.py +271 -0
  390. attune_llm/agents_md/registry.py +307 -0
  391. attune_llm/claude_memory.py +466 -0
  392. attune_llm/cli/__init__.py +8 -0
  393. attune_llm/cli/sync_claude.py +487 -0
  394. attune_llm/code_health.py +1313 -0
  395. attune_llm/commands/__init__.py +51 -0
  396. attune_llm/commands/context.py +375 -0
  397. attune_llm/commands/loader.py +301 -0
  398. attune_llm/commands/models.py +231 -0
  399. attune_llm/commands/parser.py +371 -0
  400. attune_llm/commands/registry.py +429 -0
  401. attune_llm/config/__init__.py +29 -0
  402. attune_llm/config/unified.py +291 -0
  403. attune_llm/context/__init__.py +22 -0
  404. attune_llm/context/compaction.py +455 -0
  405. attune_llm/context/manager.py +434 -0
  406. attune_llm/contextual_patterns.py +361 -0
  407. attune_llm/core.py +907 -0
  408. attune_llm/git_pattern_extractor.py +435 -0
  409. attune_llm/hooks/__init__.py +24 -0
  410. attune_llm/hooks/config.py +306 -0
  411. attune_llm/hooks/executor.py +289 -0
  412. attune_llm/hooks/registry.py +302 -0
  413. attune_llm/hooks/scripts/__init__.py +39 -0
  414. attune_llm/hooks/scripts/evaluate_session.py +201 -0
  415. attune_llm/hooks/scripts/first_time_init.py +285 -0
  416. attune_llm/hooks/scripts/pre_compact.py +207 -0
  417. attune_llm/hooks/scripts/session_end.py +183 -0
  418. attune_llm/hooks/scripts/session_start.py +163 -0
  419. attune_llm/hooks/scripts/suggest_compact.py +225 -0
  420. attune_llm/learning/__init__.py +30 -0
  421. attune_llm/learning/evaluator.py +438 -0
  422. attune_llm/learning/extractor.py +514 -0
  423. attune_llm/learning/storage.py +560 -0
  424. attune_llm/levels.py +227 -0
  425. attune_llm/pattern_confidence.py +414 -0
  426. attune_llm/pattern_resolver.py +272 -0
  427. attune_llm/pattern_summary.py +350 -0
  428. attune_llm/providers.py +967 -0
  429. attune_llm/routing/__init__.py +32 -0
  430. attune_llm/routing/model_router.py +362 -0
  431. attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
  432. attune_llm/security/PHASE2_COMPLETE.md +384 -0
  433. attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
  434. attune_llm/security/QUICK_REFERENCE.md +316 -0
  435. attune_llm/security/README.md +262 -0
  436. attune_llm/security/__init__.py +62 -0
  437. attune_llm/security/audit_logger.py +929 -0
  438. attune_llm/security/audit_logger_example.py +152 -0
  439. attune_llm/security/pii_scrubber.py +640 -0
  440. attune_llm/security/secrets_detector.py +678 -0
  441. attune_llm/security/secrets_detector_example.py +304 -0
  442. attune_llm/security/secure_memdocs.py +1192 -0
  443. attune_llm/security/secure_memdocs_example.py +278 -0
  444. attune_llm/session_status.py +745 -0
  445. attune_llm/state.py +246 -0
  446. attune_llm/utils/__init__.py +5 -0
  447. attune_llm/utils/tokens.py +349 -0
  448. attune_software/SOFTWARE_PLUGIN_README.md +57 -0
  449. attune_software/__init__.py +13 -0
  450. attune_software/cli/__init__.py +120 -0
  451. attune_software/cli/inspect.py +362 -0
  452. attune_software/cli.py +574 -0
  453. attune_software/plugin.py +188 -0
  454. workflow_scaffolding/__init__.py +11 -0
  455. workflow_scaffolding/__main__.py +12 -0
  456. workflow_scaffolding/cli.py +206 -0
  457. workflow_scaffolding/generator.py +265 -0
@@ -0,0 +1,429 @@
1
+ """Command Registry
2
+
3
+ Central registry for managing available commands.
4
+
5
+ Architectural patterns inspired by everything-claude-code by Affaan Mustafa.
6
+ See: https://github.com/affaan-m/everything-claude-code (MIT License)
7
+ See: ACKNOWLEDGMENTS.md for full attribution.
8
+
9
+ Copyright 2025 Smart AI Memory, LLC
10
+ Licensed under Fair Source 0.9
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import logging
16
+ from collections.abc import Iterator
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ from attune_llm.commands.loader import CommandLoader, get_default_commands_directory
21
+ from attune_llm.commands.models import CommandCategory, CommandConfig
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ class CommandRegistry:
27
+ """Central registry for command configurations.
28
+
29
+ Provides a single point of access for all available commands,
30
+ supporting both programmatic registration and directory loading.
31
+ Includes alias resolution for flexible command invocation.
32
+
33
+ Example:
34
+ # Create registry and load commands
35
+ registry = CommandRegistry()
36
+ registry.load_from_directory(".claude/commands/")
37
+
38
+ # Get a command by name
39
+ commit = registry.get("commit")
40
+
41
+ # Get by alias
42
+ compact = registry.get("comp") # Resolves alias
43
+
44
+ # Register a custom command
45
+ registry.register(my_custom_config)
46
+
47
+ # List all available commands
48
+ for name in registry.list_commands():
49
+ print(name)
50
+ """
51
+
52
+ _instance: CommandRegistry | None = None
53
+
54
+ def __init__(self):
55
+ """Initialize the registry."""
56
+ self._commands: dict[str, CommandConfig] = {}
57
+ self._aliases: dict[str, str] = {} # alias -> command name
58
+ self._loader: CommandLoader = CommandLoader()
59
+ self._load_paths: list[Path] = []
60
+
61
+ @classmethod
62
+ def get_instance(cls) -> CommandRegistry:
63
+ """Get the singleton registry instance.
64
+
65
+ Returns:
66
+ The global CommandRegistry instance
67
+
68
+ """
69
+ if cls._instance is None:
70
+ cls._instance = cls()
71
+ return cls._instance
72
+
73
+ @classmethod
74
+ def reset_instance(cls) -> None:
75
+ """Reset the singleton instance (mainly for testing)."""
76
+ cls._instance = None
77
+
78
+ def register(
79
+ self,
80
+ config: CommandConfig,
81
+ overwrite: bool = False,
82
+ ) -> None:
83
+ """Register a command configuration.
84
+
85
+ Args:
86
+ config: Command configuration to register
87
+ overwrite: If True, overwrite existing command with same name
88
+
89
+ Raises:
90
+ ValueError: If command name already exists and overwrite=False
91
+
92
+ """
93
+ if config.name in self._commands and not overwrite:
94
+ raise ValueError(
95
+ f"Command '{config.name}' already registered. Use overwrite=True to replace."
96
+ )
97
+
98
+ self._commands[config.name] = config
99
+
100
+ # Register aliases
101
+ for alias in config.aliases:
102
+ if alias in self._aliases and not overwrite:
103
+ logger.warning(
104
+ "Alias '%s' already registered for '%s', skipping",
105
+ alias,
106
+ self._aliases[alias],
107
+ )
108
+ continue
109
+ self._aliases[alias] = config.name
110
+
111
+ logger.debug("Registered command: %s", config.name)
112
+
113
+ def unregister(self, name: str) -> bool:
114
+ """Unregister a command by name.
115
+
116
+ Args:
117
+ name: Command name to remove
118
+
119
+ Returns:
120
+ True if command was found and removed
121
+
122
+ """
123
+ if name in self._commands:
124
+ config = self._commands[name]
125
+
126
+ # Remove aliases
127
+ for alias in config.aliases:
128
+ if self._aliases.get(alias) == name:
129
+ del self._aliases[alias]
130
+
131
+ del self._commands[name]
132
+ logger.debug("Unregistered command: %s", name)
133
+ return True
134
+ return False
135
+
136
+ def get(self, name: str) -> CommandConfig | None:
137
+ """Get a command configuration by name or alias.
138
+
139
+ Args:
140
+ name: Command name or alias
141
+
142
+ Returns:
143
+ Command config or None if not found
144
+
145
+ """
146
+ # Direct lookup
147
+ if name in self._commands:
148
+ return self._commands[name]
149
+
150
+ # Alias lookup
151
+ if name in self._aliases:
152
+ return self._commands.get(self._aliases[name])
153
+
154
+ return None
155
+
156
+ def get_required(self, name: str) -> CommandConfig:
157
+ """Get a command configuration, raising if not found.
158
+
159
+ Args:
160
+ name: Command name or alias
161
+
162
+ Returns:
163
+ Command configuration
164
+
165
+ Raises:
166
+ KeyError: If command not found
167
+
168
+ """
169
+ config = self.get(name)
170
+ if config is None:
171
+ available = ", ".join(sorted(self._commands.keys()))
172
+ raise KeyError(f"Command '{name}' not found. Available commands: {available}")
173
+ return config
174
+
175
+ def has(self, name: str) -> bool:
176
+ """Check if a command is registered.
177
+
178
+ Args:
179
+ name: Command name or alias
180
+
181
+ Returns:
182
+ True if command exists
183
+
184
+ """
185
+ return name in self._commands or name in self._aliases
186
+
187
+ def resolve_alias(self, name: str) -> str:
188
+ """Resolve an alias to command name.
189
+
190
+ Args:
191
+ name: Name or alias
192
+
193
+ Returns:
194
+ Resolved command name
195
+
196
+ """
197
+ return self._aliases.get(name, name)
198
+
199
+ def list_commands(self) -> list[str]:
200
+ """Get list of all registered command names.
201
+
202
+ Returns:
203
+ Sorted list of command names
204
+
205
+ """
206
+ return sorted(self._commands.keys())
207
+
208
+ def list_aliases(self) -> dict[str, str]:
209
+ """Get all registered aliases.
210
+
211
+ Returns:
212
+ Dictionary mapping aliases to command names
213
+
214
+ """
215
+ return dict(self._aliases)
216
+
217
+ def iter_commands(self) -> Iterator[CommandConfig]:
218
+ """Iterate over all registered commands.
219
+
220
+ Yields:
221
+ Command configurations
222
+
223
+ """
224
+ for name in sorted(self._commands.keys()):
225
+ yield self._commands[name]
226
+
227
+ def load_from_directory(
228
+ self,
229
+ directory: str | Path,
230
+ recursive: bool = False,
231
+ overwrite: bool = False,
232
+ ) -> int:
233
+ """Load commands from a directory.
234
+
235
+ Args:
236
+ directory: Directory containing .md command files
237
+ recursive: If True, scan subdirectories
238
+ overwrite: If True, overwrite existing commands
239
+
240
+ Returns:
241
+ Number of commands loaded
242
+
243
+ """
244
+ directory = Path(directory)
245
+ # Track loaded paths for reload (avoid duplicates)
246
+ if directory not in self._load_paths:
247
+ self._load_paths.append(directory)
248
+
249
+ commands = self._loader.load_directory(directory, recursive=recursive)
250
+
251
+ loaded = 0
252
+ for _name, config in commands.items():
253
+ try:
254
+ self.register(config, overwrite=overwrite)
255
+ loaded += 1
256
+ except ValueError as e:
257
+ logger.warning("Skipping command: %s", e)
258
+
259
+ logger.info("Loaded %d command(s) from %s", loaded, directory)
260
+ return loaded
261
+
262
+ def load_from_file(
263
+ self,
264
+ file_path: str | Path,
265
+ overwrite: bool = False,
266
+ ) -> CommandConfig:
267
+ """Load a single command from a file.
268
+
269
+ Args:
270
+ file_path: Path to command markdown file
271
+ overwrite: If True, overwrite existing command
272
+
273
+ Returns:
274
+ Loaded command configuration
275
+
276
+ """
277
+ config = self._loader.load(file_path)
278
+ self.register(config, overwrite=overwrite)
279
+ return config
280
+
281
+ def load_default_commands(self, overwrite: bool = False) -> int:
282
+ """Load commands from default directory.
283
+
284
+ Args:
285
+ overwrite: If True, overwrite existing commands
286
+
287
+ Returns:
288
+ Number of commands loaded
289
+
290
+ """
291
+ default_dir = get_default_commands_directory()
292
+
293
+ if not default_dir.exists():
294
+ logger.info("Default commands directory not found: %s", default_dir)
295
+ return 0
296
+
297
+ return self.load_from_directory(default_dir, overwrite=overwrite)
298
+
299
+ def reload(self) -> int:
300
+ """Reload all commands from previously loaded directories.
301
+
302
+ Returns:
303
+ Total number of commands after reload
304
+
305
+ """
306
+ self._commands.clear()
307
+ self._aliases.clear()
308
+
309
+ # Copy _load_paths and clear it to avoid duplicates when load_from_directory appends
310
+ paths_to_reload = list(self._load_paths)
311
+ self._load_paths.clear()
312
+
313
+ for directory in paths_to_reload:
314
+ if directory.exists():
315
+ self.load_from_directory(directory, overwrite=True)
316
+
317
+ return len(self._commands)
318
+
319
+ def get_by_category(self, category: CommandCategory) -> list[CommandConfig]:
320
+ """Get all commands with a specific category.
321
+
322
+ Args:
323
+ category: Category to filter by
324
+
325
+ Returns:
326
+ List of matching command configs
327
+
328
+ """
329
+ return [config for config in self._commands.values() if config.category == category]
330
+
331
+ def get_by_tag(self, tag: str) -> list[CommandConfig]:
332
+ """Get all commands with a specific tag.
333
+
334
+ Args:
335
+ tag: Tag to filter by
336
+
337
+ Returns:
338
+ List of matching command configs
339
+
340
+ """
341
+ tag = tag.lower()
342
+ return [
343
+ config
344
+ for config in self._commands.values()
345
+ if tag in [t.lower() for t in config.metadata.tags]
346
+ ]
347
+
348
+ def search(self, query: str) -> list[CommandConfig]:
349
+ """Search commands by name, description, or tags.
350
+
351
+ Args:
352
+ query: Search query
353
+
354
+ Returns:
355
+ List of matching commands
356
+
357
+ """
358
+ query = query.lower()
359
+ results: list[CommandConfig] = []
360
+
361
+ for config in self._commands.values():
362
+ if query in config.name.lower():
363
+ results.append(config)
364
+ elif query in config.description.lower():
365
+ results.append(config)
366
+ elif any(query in tag.lower() for tag in config.metadata.tags):
367
+ results.append(config)
368
+
369
+ return results
370
+
371
+ def get_summary(self) -> dict[str, Any]:
372
+ """Get a summary of registered commands.
373
+
374
+ Returns:
375
+ Summary dictionary
376
+
377
+ """
378
+ by_category: dict[str, int] = {}
379
+
380
+ for config in self._commands.values():
381
+ cat = config.category.value
382
+ by_category[cat] = by_category.get(cat, 0) + 1
383
+
384
+ return {
385
+ "total_commands": len(self._commands),
386
+ "total_aliases": len(self._aliases),
387
+ "command_names": self.list_commands(),
388
+ "by_category": by_category,
389
+ "load_paths": [str(p) for p in self._load_paths],
390
+ }
391
+
392
+ def format_help(self) -> str:
393
+ """Format help text listing all commands.
394
+
395
+ Returns:
396
+ Formatted help string
397
+
398
+ """
399
+ lines = ["# Available Commands", ""]
400
+
401
+ # Group by category
402
+ by_category: dict[CommandCategory, list[CommandConfig]] = {}
403
+ for config in self._commands.values():
404
+ cat = config.category
405
+ if cat not in by_category:
406
+ by_category[cat] = []
407
+ by_category[cat].append(config)
408
+
409
+ for category in CommandCategory:
410
+ commands = by_category.get(category, [])
411
+ if not commands:
412
+ continue
413
+
414
+ lines.append(f"## {category.value.title()}")
415
+ lines.append("")
416
+
417
+ for config in sorted(commands, key=lambda c: c.name):
418
+ lines.append(config.format_for_display())
419
+
420
+ lines.append("")
421
+
422
+ return "\n".join(lines)
423
+
424
+ def clear(self) -> None:
425
+ """Clear all registered commands."""
426
+ self._commands.clear()
427
+ self._aliases.clear()
428
+ self._load_paths.clear()
429
+ logger.debug("Cleared command registry")
@@ -0,0 +1,29 @@
1
+ """Empathy Framework Configuration Module
2
+
3
+ Provides unified configuration models for agents, wizards, and workflows.
4
+
5
+ Copyright 2025 Smart-AI-Memory
6
+ Licensed under Fair Source License 0.9
7
+ """
8
+
9
+ from attune_llm.config.unified import (
10
+ AgentOperationError,
11
+ BookProductionConfig,
12
+ MemDocsConfig,
13
+ ModelTier,
14
+ Provider,
15
+ RedisConfig,
16
+ UnifiedAgentConfig,
17
+ WorkflowMode,
18
+ )
19
+
20
+ __all__ = [
21
+ "AgentOperationError",
22
+ "BookProductionConfig",
23
+ "MemDocsConfig",
24
+ "ModelTier",
25
+ "Provider",
26
+ "RedisConfig",
27
+ "UnifiedAgentConfig",
28
+ "WorkflowMode",
29
+ ]