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,483 @@
1
+ """CrewAI Adapter
2
+
3
+ Creates agents using CrewAI's role/goal/backstory pattern while integrating
4
+ with Empathy's cost optimization and pattern learning.
5
+
6
+ CrewAI is a multi-agent framework focusing on:
7
+ - Role-based agents with goals and backstories
8
+ - Hierarchical and sequential crew orchestration
9
+ - Task delegation and collaboration
10
+
11
+ Requires: pip install crewai
12
+
13
+ Copyright 2025 Smart-AI-Memory
14
+ Licensed under Fair Source License 0.9
15
+ """
16
+
17
+ import asyncio
18
+ import os
19
+ from collections.abc import Callable
20
+ from typing import Any
21
+
22
+ from attune_llm.agent_factory.base import (
23
+ AgentConfig,
24
+ AgentRole,
25
+ BaseAdapter,
26
+ BaseAgent,
27
+ BaseWorkflow,
28
+ WorkflowConfig,
29
+ )
30
+
31
+ # Lazy imports for CrewAI
32
+ _crewai_available = None
33
+
34
+
35
+ def _check_crewai():
36
+ """Check if CrewAI is available."""
37
+ global _crewai_available
38
+ if _crewai_available is None:
39
+ try:
40
+ import crewai # noqa: F401
41
+
42
+ _crewai_available = True
43
+ except (ImportError, AttributeError):
44
+ # INTENTIONAL: Catch AttributeError for CrewAI 0.203.x RAG module import issues
45
+ # ImportError: CrewAI not installed
46
+ # AttributeError: CrewAI 0.203.x has RAG module attribute protection issues
47
+ _crewai_available = False
48
+ return _crewai_available
49
+
50
+
51
+ class CrewAIAgent(BaseAgent):
52
+ """Agent wrapping a CrewAI Agent."""
53
+
54
+ def __init__(self, config: AgentConfig, crewai_agent=None):
55
+ """Initialize CrewAI agent wrapper.
56
+
57
+ Args:
58
+ config: Agent configuration
59
+ crewai_agent: The underlying CrewAI Agent instance
60
+
61
+ """
62
+ super().__init__(config)
63
+ self._crewai_agent = crewai_agent
64
+
65
+ async def invoke(self, input_data: str | dict, context: dict | None = None) -> dict:
66
+ """Invoke the CrewAI agent.
67
+
68
+ CrewAI agents work within crews/tasks, so we create a temporary
69
+ task for standalone invocation.
70
+ """
71
+ if not self._crewai_agent:
72
+ return {"output": "No CrewAI agent configured", "metadata": {}}
73
+
74
+ try:
75
+ from crewai import Task
76
+
77
+ # Format input as task description
78
+ if isinstance(input_data, str):
79
+ description = input_data
80
+ else:
81
+ description = input_data.get("task", input_data.get("input", str(input_data)))
82
+
83
+ # Add context to description if provided
84
+ if context:
85
+ context_str = "\n".join(f"{k}: {v}" for k, v in context.items())
86
+ description = f"{description}\n\nContext:\n{context_str}"
87
+
88
+ # Create and execute task
89
+ task = Task(
90
+ description=description,
91
+ expected_output="A comprehensive response addressing the task.",
92
+ agent=self._crewai_agent,
93
+ )
94
+
95
+ # CrewAI is primarily sync, so run in executor
96
+ loop = asyncio.get_event_loop()
97
+ result = await loop.run_in_executor(None, self._execute_task, task)
98
+
99
+ output = str(result) if result else "Task completed"
100
+
101
+ # Track conversation
102
+ self._conversation_history.append({"role": "user", "content": description})
103
+ self._conversation_history.append({"role": "assistant", "content": output})
104
+
105
+ return {
106
+ "output": output,
107
+ "metadata": {
108
+ "model": self.model,
109
+ "framework": "crewai",
110
+ "agent_role": self._crewai_agent.role if self._crewai_agent else None,
111
+ },
112
+ }
113
+
114
+ except Exception as e:
115
+ return {
116
+ "output": f"Error: {e!s}",
117
+ "metadata": {"error": str(e), "framework": "crewai"},
118
+ }
119
+
120
+ def _execute_task(self, task):
121
+ """Execute a CrewAI task synchronously."""
122
+ try:
123
+ # In newer versions of CrewAI, tasks are executed via Crew
124
+ # For standalone execution, we use the agent's execute_task method
125
+ if hasattr(task, "execute"):
126
+ return task.execute()
127
+ if hasattr(self._crewai_agent, "execute_task"):
128
+ return self._crewai_agent.execute_task(task)
129
+ # Fallback: create minimal crew
130
+ from crewai import Crew
131
+
132
+ crew = Crew(agents=[self._crewai_agent], tasks=[task], verbose=False)
133
+ return crew.kickoff()
134
+ except Exception as e:
135
+ return f"Task execution error: {e}"
136
+
137
+ async def stream(self, input_data: str | dict, context: dict | None = None):
138
+ """Stream CrewAI response.
139
+
140
+ Note: CrewAI doesn't natively support streaming, so we simulate
141
+ by yielding the complete response.
142
+ """
143
+ result = await self.invoke(input_data, context)
144
+ yield result
145
+
146
+ @property
147
+ def crewai_agent(self):
148
+ """Get the underlying CrewAI agent."""
149
+ return self._crewai_agent
150
+
151
+
152
+ class CrewAIWorkflow(BaseWorkflow):
153
+ """Workflow using CrewAI's Crew orchestration."""
154
+
155
+ def __init__(self, config: WorkflowConfig, agents: list[BaseAgent], crew=None):
156
+ """Initialize CrewAI workflow.
157
+
158
+ Args:
159
+ config: Workflow configuration
160
+ agents: List of CrewAIAgent instances
161
+ crew: Optional pre-built CrewAI Crew instance
162
+
163
+ """
164
+ super().__init__(config, agents)
165
+ self._crew = crew
166
+ self._tasks: list = []
167
+
168
+ async def run(self, input_data: str | dict, initial_state: dict | None = None) -> dict:
169
+ """Run the CrewAI crew workflow."""
170
+ self._state = initial_state or {}
171
+
172
+ if not self._crew:
173
+ return {"output": "No CrewAI Crew configured", "error": "Missing crew"}
174
+
175
+ try:
176
+ # Format input
177
+ if isinstance(input_data, str):
178
+ inputs = {"input": input_data}
179
+ else:
180
+ inputs = dict(input_data)
181
+
182
+ # Add state to inputs
183
+ inputs.update(self._state)
184
+
185
+ # Run crew in executor (CrewAI is sync)
186
+ loop = asyncio.get_event_loop()
187
+ result = await loop.run_in_executor(None, self._crew.kickoff, inputs)
188
+
189
+ output = str(result) if result else "Crew completed"
190
+
191
+ return {
192
+ "output": output,
193
+ "results": [{"crew_result": str(result)}],
194
+ "state": self._state,
195
+ "metadata": {"framework": "crewai"},
196
+ }
197
+
198
+ except Exception as e:
199
+ return {
200
+ "output": f"Crew execution error: {e}",
201
+ "error": str(e),
202
+ "state": self._state,
203
+ }
204
+
205
+ async def stream(self, input_data: str | dict, initial_state: dict | None = None):
206
+ """Stream workflow execution.
207
+
208
+ Note: CrewAI doesn't support streaming, so we yield progress updates.
209
+ """
210
+ yield {"event": "crew_start", "crew": self.config.name}
211
+
212
+ result = await self.run(input_data, initial_state)
213
+
214
+ yield {"event": "crew_end", "result": result}
215
+
216
+ def add_task(self, description: str, expected_output: str, agent_name: str) -> None:
217
+ """Add a task to the workflow.
218
+
219
+ Args:
220
+ description: Task description
221
+ expected_output: Expected output description
222
+ agent_name: Name of agent to assign task to
223
+
224
+ """
225
+ if not _check_crewai():
226
+ return
227
+
228
+ from crewai import Task
229
+
230
+ agent = self.agents.get(agent_name)
231
+ if agent and hasattr(agent, "crewai_agent"):
232
+ task = Task(
233
+ description=description,
234
+ expected_output=expected_output,
235
+ agent=agent.crewai_agent,
236
+ )
237
+ self._tasks.append(task)
238
+
239
+
240
+ class CrewAIAdapter(BaseAdapter):
241
+ """Adapter for CrewAI framework."""
242
+
243
+ def __init__(self, provider: str = "openai", api_key: str | None = None):
244
+ """Initialize CrewAI adapter.
245
+
246
+ Args:
247
+ provider: LLM provider (openai is default for CrewAI)
248
+ api_key: API key (uses env var if not provided)
249
+
250
+ """
251
+ self.provider = provider
252
+ self.api_key = api_key or os.getenv(
253
+ "OPENAI_API_KEY" if provider == "openai" else "ANTHROPIC_API_KEY",
254
+ )
255
+
256
+ @property
257
+ def framework_name(self) -> str:
258
+ return "crewai"
259
+
260
+ def is_available(self) -> bool:
261
+ """Check if CrewAI is installed."""
262
+ return bool(_check_crewai())
263
+
264
+ def create_agent(self, config: AgentConfig) -> CrewAIAgent:
265
+ """Create a CrewAI-based agent."""
266
+ if not self.is_available():
267
+ raise ImportError("CrewAI not installed. Run: pip install crewai")
268
+
269
+ from crewai import Agent
270
+
271
+ # Map Empathy role to CrewAI role string
272
+ role = self._map_role(config.role)
273
+
274
+ # Generate goal based on role and description
275
+ goal = config.description or self._default_goal(config.role)
276
+
277
+ # Generate backstory from system prompt or role
278
+ backstory = config.system_prompt or self._default_backstory(config.role)
279
+
280
+ # Convert tools to CrewAI format
281
+ crewai_tools = [self._convert_tool(t) for t in config.tools if t]
282
+ crewai_tools = [t for t in crewai_tools if t is not None]
283
+
284
+ # Create CrewAI agent
285
+ crewai_agent = Agent(
286
+ role=role,
287
+ goal=goal,
288
+ backstory=backstory,
289
+ tools=crewai_tools if crewai_tools else None,
290
+ verbose=False,
291
+ allow_delegation=config.role == AgentRole.COORDINATOR,
292
+ )
293
+
294
+ return CrewAIAgent(config, crewai_agent)
295
+
296
+ def create_workflow(self, config: WorkflowConfig, agents: list[BaseAgent]) -> CrewAIWorkflow:
297
+ """Create a CrewAI Crew workflow."""
298
+ if not self.is_available():
299
+ raise ImportError("CrewAI not installed")
300
+
301
+ from crewai import Crew, Process
302
+
303
+ # Determine process type from workflow mode
304
+ if config.mode == "hierarchical":
305
+ process = Process.hierarchical
306
+ else:
307
+ process = Process.sequential
308
+
309
+ # Extract CrewAI agents from wrappers
310
+ crewai_agents = []
311
+ for agent in agents:
312
+ if isinstance(agent, CrewAIAgent) and agent.crewai_agent:
313
+ crewai_agents.append(agent.crewai_agent)
314
+
315
+ if not crewai_agents:
316
+ return CrewAIWorkflow(config, agents)
317
+
318
+ # Create Crew with manager_llm for hierarchical process
319
+ crew_kwargs = {
320
+ "agents": crewai_agents,
321
+ "tasks": [], # Tasks will be added dynamically or via add_task
322
+ "process": process,
323
+ "verbose": False,
324
+ }
325
+
326
+ # Hierarchical process requires manager_llm
327
+ if config.mode == "hierarchical":
328
+ # Try langchain_openai first (preferred by CrewAI)
329
+ try:
330
+ from langchain_openai import ChatOpenAI
331
+
332
+ crew_kwargs["manager_llm"] = ChatOpenAI(
333
+ model="gpt-4o-mini",
334
+ temperature=0.7,
335
+ )
336
+ except ImportError:
337
+ # Fallback: Use CrewAI's native LLM class
338
+ from crewai import LLM
339
+
340
+ crew_kwargs["manager_llm"] = LLM(
341
+ model="gpt-4o-mini",
342
+ temperature=0.7,
343
+ )
344
+
345
+ crew = Crew(**crew_kwargs)
346
+
347
+ return CrewAIWorkflow(config, agents, crew)
348
+
349
+ def create_tool(
350
+ self,
351
+ name: str,
352
+ description: str,
353
+ func: Callable,
354
+ args_schema: dict | None = None,
355
+ ) -> Any:
356
+ """Create a CrewAI tool."""
357
+ if not self.is_available():
358
+ return super().create_tool(name, description, func, args_schema)
359
+
360
+ try:
361
+ from crewai.tools import BaseTool
362
+
363
+ # Capture function parameters in closure variables
364
+ tool_name = name
365
+ tool_description = description
366
+ tool_func = func
367
+
368
+ # Create dynamic tool class
369
+ class DynamicTool(BaseTool):
370
+ name: str = tool_name
371
+ description: str = tool_description
372
+
373
+ def _run(self, **kwargs) -> str:
374
+ return str(tool_func(**kwargs))
375
+
376
+ return DynamicTool()
377
+ except ImportError:
378
+ # Fallback to dict format
379
+ return {"name": name, "description": description, "func": func}
380
+
381
+ def _convert_tool(self, tool: Any) -> Any:
382
+ """Convert a tool to CrewAI format."""
383
+ if not self.is_available():
384
+ return None
385
+
386
+ # If already a CrewAI tool, return as-is
387
+ try:
388
+ from crewai.tools import BaseTool
389
+
390
+ if isinstance(tool, BaseTool):
391
+ return tool
392
+ except ImportError:
393
+ pass
394
+
395
+ # If dict, convert to CrewAI tool
396
+ if isinstance(tool, dict):
397
+ return self.create_tool(
398
+ name=tool.get("name", "tool"),
399
+ description=tool.get("description", ""),
400
+ func=tool.get("func", lambda: None),
401
+ args_schema=tool.get("args_schema"),
402
+ )
403
+
404
+ return None
405
+
406
+ def _map_role(self, role: AgentRole) -> str:
407
+ """Map Empathy AgentRole to CrewAI role string."""
408
+ role_map = {
409
+ AgentRole.COORDINATOR: "Project Manager",
410
+ AgentRole.RESEARCHER: "Senior Researcher",
411
+ AgentRole.WRITER: "Content Writer",
412
+ AgentRole.REVIEWER: "Quality Reviewer",
413
+ AgentRole.EDITOR: "Editor",
414
+ AgentRole.EXECUTOR: "Task Executor",
415
+ AgentRole.DEBUGGER: "Software Debugger",
416
+ AgentRole.SECURITY: "Security Analyst",
417
+ AgentRole.ARCHITECT: "Software Architect",
418
+ AgentRole.TESTER: "QA Tester",
419
+ AgentRole.DOCUMENTER: "Technical Writer",
420
+ AgentRole.RETRIEVER: "Information Retriever",
421
+ AgentRole.SUMMARIZER: "Content Summarizer",
422
+ AgentRole.ANSWERER: "Question Answerer",
423
+ AgentRole.CUSTOM: "Specialist",
424
+ }
425
+ return role_map.get(role, "Specialist")
426
+
427
+ def _default_goal(self, role: AgentRole) -> str:
428
+ """Generate default goal based on role."""
429
+ goal_map = {
430
+ AgentRole.COORDINATOR: "Coordinate team efforts and ensure project success",
431
+ AgentRole.RESEARCHER: "Conduct thorough research and gather comprehensive information",
432
+ AgentRole.WRITER: "Create clear, engaging, and high-quality content",
433
+ AgentRole.REVIEWER: "Provide constructive feedback and ensure quality standards",
434
+ AgentRole.EDITOR: "Refine and improve content for clarity and impact",
435
+ AgentRole.EXECUTOR: "Execute tasks efficiently and report results accurately",
436
+ AgentRole.DEBUGGER: "Identify and resolve software bugs systematically",
437
+ AgentRole.SECURITY: "Analyze systems for security vulnerabilities",
438
+ AgentRole.ARCHITECT: "Design robust and scalable system architectures",
439
+ AgentRole.TESTER: "Create comprehensive tests and ensure software quality",
440
+ AgentRole.DOCUMENTER: "Create clear and comprehensive documentation",
441
+ AgentRole.RETRIEVER: "Retrieve relevant information from knowledge bases",
442
+ AgentRole.SUMMARIZER: "Create concise and accurate summaries",
443
+ AgentRole.ANSWERER: "Provide accurate answers to questions",
444
+ AgentRole.CUSTOM: "Complete assigned tasks with excellence",
445
+ }
446
+ return goal_map.get(role, "Complete assigned tasks with excellence")
447
+
448
+ def _default_backstory(self, role: AgentRole) -> str:
449
+ """Generate default backstory based on role."""
450
+ backstory_map = {
451
+ AgentRole.COORDINATOR: (
452
+ "You are an experienced project manager with a track record of "
453
+ "successfully coordinating complex projects and diverse teams."
454
+ ),
455
+ AgentRole.RESEARCHER: (
456
+ "You are a meticulous researcher with expertise in finding "
457
+ "reliable information and synthesizing complex topics."
458
+ ),
459
+ AgentRole.WRITER: (
460
+ "You are a skilled writer with years of experience crafting "
461
+ "compelling narratives and clear technical content."
462
+ ),
463
+ AgentRole.REVIEWER: (
464
+ "You are a seasoned reviewer known for your attention to detail "
465
+ "and constructive feedback that improves quality."
466
+ ),
467
+ AgentRole.DEBUGGER: (
468
+ "You are an expert debugger with deep knowledge of software systems "
469
+ "and a systematic approach to problem-solving."
470
+ ),
471
+ AgentRole.SECURITY: (
472
+ "You are a security analyst with expertise in identifying "
473
+ "vulnerabilities and recommending protective measures."
474
+ ),
475
+ AgentRole.ARCHITECT: (
476
+ "You are a software architect with experience designing "
477
+ "scalable, maintainable systems for enterprise applications."
478
+ ),
479
+ }
480
+ return backstory_map.get(
481
+ role,
482
+ f"You are an experienced professional excelling as a {role.value}.",
483
+ )