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,193 @@
1
+ """Framework Enumeration and Detection
2
+
3
+ Defines supported agent frameworks and provides utilities for
4
+ detecting installed frameworks and selecting defaults.
5
+
6
+ Copyright 2025 Smart-AI-Memory
7
+ Licensed under Fair Source License 0.9
8
+ """
9
+
10
+ from enum import Enum
11
+
12
+
13
+ class Framework(Enum):
14
+ """Supported agent frameworks."""
15
+
16
+ # Empathy native (no external deps)
17
+ NATIVE = "native"
18
+
19
+ # LangChain ecosystem
20
+ LANGCHAIN = "langchain"
21
+ LANGGRAPH = "langgraph"
22
+
23
+ # Microsoft AutoGen
24
+ AUTOGEN = "autogen"
25
+
26
+ # deepset Haystack
27
+ HAYSTACK = "haystack"
28
+
29
+ # CrewAI
30
+ CREWAI = "crewai"
31
+
32
+ @classmethod
33
+ def from_string(cls, name: str) -> "Framework":
34
+ """Convert string to Framework enum."""
35
+ name_lower = name.lower().strip()
36
+ mapping = {
37
+ "native": cls.NATIVE,
38
+ "empathy": cls.NATIVE,
39
+ "langchain": cls.LANGCHAIN,
40
+ "langgraph": cls.LANGGRAPH,
41
+ "lang_graph": cls.LANGGRAPH,
42
+ "autogen": cls.AUTOGEN,
43
+ "auto_gen": cls.AUTOGEN,
44
+ "haystack": cls.HAYSTACK,
45
+ "crewai": cls.CREWAI,
46
+ "crew_ai": cls.CREWAI,
47
+ "crew": cls.CREWAI,
48
+ }
49
+ if name_lower in mapping:
50
+ return mapping[name_lower]
51
+ raise ValueError(f"Unknown framework: {name}. Available: {list(mapping.keys())}")
52
+
53
+
54
+ def detect_installed_frameworks() -> list[Framework]:
55
+ """Detect which agent frameworks are installed.
56
+
57
+ Returns:
58
+ List of installed frameworks (native is always included)
59
+
60
+ """
61
+ installed = [Framework.NATIVE]
62
+
63
+ # Check LangChain
64
+ try:
65
+ import langchain # noqa: F401
66
+
67
+ installed.append(Framework.LANGCHAIN)
68
+ except ImportError:
69
+ pass
70
+
71
+ # Check LangGraph
72
+ try:
73
+ import langgraph # noqa: F401
74
+
75
+ installed.append(Framework.LANGGRAPH)
76
+ except ImportError:
77
+ pass
78
+
79
+ # Check AutoGen
80
+ try:
81
+ import autogen # noqa: F401
82
+
83
+ installed.append(Framework.AUTOGEN)
84
+ except ImportError:
85
+ pass
86
+
87
+ # Check Haystack
88
+ try:
89
+ import haystack # noqa: F401
90
+
91
+ installed.append(Framework.HAYSTACK)
92
+ except ImportError:
93
+ pass
94
+
95
+ # Check CrewAI
96
+ try:
97
+ import crewai # noqa: F401
98
+
99
+ installed.append(Framework.CREWAI)
100
+ except (ImportError, AttributeError, ImportWarning):
101
+ # INTENTIONAL: Catch import-time errors from CrewAI dependencies
102
+ pass
103
+
104
+ return installed
105
+
106
+
107
+ def get_recommended_framework(use_case: str = "general") -> Framework:
108
+ """Get recommended framework for a use case.
109
+
110
+ Args:
111
+ use_case: One of "general", "rag", "multi_agent", "code_analysis", "workflow"
112
+
113
+ Returns:
114
+ Recommended framework based on installed packages and use case
115
+
116
+ """
117
+ installed = detect_installed_frameworks()
118
+
119
+ recommendations = {
120
+ "general": [Framework.LANGGRAPH, Framework.LANGCHAIN, Framework.NATIVE],
121
+ "rag": [Framework.HAYSTACK, Framework.LANGCHAIN, Framework.NATIVE],
122
+ "multi_agent": [Framework.AUTOGEN, Framework.LANGGRAPH, Framework.NATIVE],
123
+ "code_analysis": [Framework.LANGGRAPH, Framework.LANGCHAIN, Framework.NATIVE],
124
+ "workflow": [Framework.LANGGRAPH, Framework.LANGCHAIN, Framework.NATIVE],
125
+ "conversational": [Framework.AUTOGEN, Framework.LANGCHAIN, Framework.NATIVE],
126
+ }
127
+
128
+ preferred = recommendations.get(use_case, recommendations["general"])
129
+
130
+ for framework in preferred:
131
+ if framework in installed:
132
+ return framework
133
+
134
+ return Framework.NATIVE
135
+
136
+
137
+ def get_framework_info(framework: Framework) -> dict[str, object]:
138
+ """Get information about a framework.
139
+
140
+ Returns:
141
+ Dict with name, description, best_for, install_command
142
+
143
+ """
144
+ info: dict[Framework, dict[str, object]] = {
145
+ Framework.NATIVE: {
146
+ "name": "Empathy Native",
147
+ "description": "Built-in agent system with EmpathyLLM integration",
148
+ "best_for": ["Simple agents", "Cost optimization", "Pattern learning"],
149
+ "install_command": None,
150
+ "docs_url": "https://smartaimemory.com/docs/agents",
151
+ },
152
+ Framework.LANGCHAIN: {
153
+ "name": "LangChain",
154
+ "description": "Composable chains with tools, memory, and retrieval",
155
+ "best_for": ["Tool usage", "RAG", "Chains", "Prompt templates"],
156
+ "install_command": "pip install langchain langchain-anthropic",
157
+ "docs_url": "https://python.langchain.com/docs/",
158
+ },
159
+ Framework.LANGGRAPH: {
160
+ "name": "LangGraph",
161
+ "description": "Stateful, multi-actor workflows with cycles",
162
+ "best_for": ["Complex workflows", "Stateful agents", "Multi-step reasoning"],
163
+ "install_command": "pip install langgraph langchain-anthropic",
164
+ "docs_url": "https://langchain-ai.github.io/langgraph/",
165
+ },
166
+ Framework.AUTOGEN: {
167
+ "name": "AutoGen",
168
+ "description": "Multi-agent conversational systems",
169
+ "best_for": ["Agent teams", "Conversations", "Code execution"],
170
+ "install_command": "pip install pyautogen",
171
+ "docs_url": "https://microsoft.github.io/autogen/",
172
+ },
173
+ Framework.HAYSTACK: {
174
+ "name": "Haystack",
175
+ "description": "Production-ready RAG and NLP pipelines",
176
+ "best_for": ["Document QA", "RAG", "Search", "NLP pipelines"],
177
+ "install_command": "pip install haystack-ai",
178
+ "docs_url": "https://docs.haystack.deepset.ai/",
179
+ },
180
+ Framework.CREWAI: {
181
+ "name": "CrewAI",
182
+ "description": "Role-based multi-agent framework with goal-oriented crews",
183
+ "best_for": [
184
+ "Agent teams",
185
+ "Role-playing",
186
+ "Task delegation",
187
+ "Hierarchical workflows",
188
+ ],
189
+ "install_command": "pip install crewai",
190
+ "docs_url": "https://docs.crewai.com/",
191
+ },
192
+ }
193
+ return info.get(framework, info[Framework.NATIVE])
@@ -0,0 +1,328 @@
1
+ """Memory-Aware Agent Wrapper
2
+
3
+ Integrates agents with the Memory Graph for cross-agent learning.
4
+ Agents can query for similar past findings and store new findings
5
+ for other agents to benefit from.
6
+
7
+ Usage:
8
+ from attune_llm.agent_factory import AgentFactory
9
+ from attune_llm.agent_factory.memory_integration import MemoryAwareAgent
10
+
11
+ factory = AgentFactory()
12
+ agent = factory.create_agent(
13
+ name="bug_hunter",
14
+ role="debugger",
15
+ memory_graph_enabled=True
16
+ )
17
+
18
+ # Agent will automatically:
19
+ # 1. Query similar past bugs before invocation
20
+ # 2. Store new findings after invocation
21
+
22
+ Copyright 2025 Smart-AI-Memory
23
+ Licensed under Fair Source License 0.9
24
+ """
25
+
26
+ import logging
27
+ from typing import Any
28
+
29
+ from attune_llm.agent_factory.base import BaseAgent
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ class MemoryAwareAgent(BaseAgent):
35
+ """Agent wrapper that integrates with Memory Graph.
36
+
37
+ Enables cross-agent learning by:
38
+ - Querying similar past findings before invocation
39
+ - Storing new findings after invocation
40
+ - Connecting findings across agents
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ agent: BaseAgent,
46
+ graph_path: str = "patterns/memory_graph.json",
47
+ store_findings: bool = True,
48
+ query_similar: bool = True,
49
+ similarity_threshold: float = 0.4,
50
+ max_similar_results: int = 5,
51
+ ):
52
+ """Initialize memory-aware agent wrapper.
53
+
54
+ Args:
55
+ agent: The underlying agent to wrap
56
+ graph_path: Path to memory graph JSON file
57
+ store_findings: Whether to store findings in memory graph
58
+ query_similar: Whether to query for similar findings
59
+ similarity_threshold: Minimum similarity score for results
60
+ max_similar_results: Maximum similar findings to return
61
+
62
+ """
63
+ super().__init__(agent.config)
64
+ self._wrapped = agent
65
+ self._graph_path = graph_path
66
+ self._store_findings = store_findings
67
+ self._query_similar = query_similar
68
+ self._similarity_threshold = similarity_threshold
69
+ self._max_similar_results = max_similar_results
70
+ self._graph: Any = None
71
+
72
+ self._init_graph()
73
+
74
+ def _init_graph(self) -> None:
75
+ """Initialize connection to Memory Graph."""
76
+ try:
77
+ from attune.memory import MemoryGraph
78
+
79
+ self._graph = MemoryGraph(path=self._graph_path)
80
+ logger.debug(f"Memory graph loaded from {self._graph_path}")
81
+ except ImportError:
82
+ logger.warning("attune.memory not available, memory integration disabled")
83
+ except Exception as e:
84
+ logger.warning(f"Failed to load memory graph: {e}")
85
+
86
+ async def invoke(self, input_data: str | dict, context: dict | None = None) -> dict:
87
+ """Invoke the agent with memory graph integration.
88
+
89
+ 1. Query for similar past findings
90
+ 2. Add context from similar findings
91
+ 3. Invoke wrapped agent
92
+ 4. Store any new findings
93
+
94
+ Args:
95
+ input_data: User input or structured data
96
+ context: Optional context (previous results, shared state)
97
+
98
+ Returns:
99
+ Dict with at least {"output": str, "metadata": dict}
100
+
101
+ """
102
+ context = context or {}
103
+
104
+ # 1. Query for similar findings if enabled
105
+ if self._query_similar and self._graph:
106
+ similar_findings = self._get_similar_findings(input_data)
107
+ if similar_findings:
108
+ context["similar_findings"] = similar_findings
109
+ context["memory_graph_hits"] = len(similar_findings)
110
+
111
+ # 2. Invoke wrapped agent with enhanced context
112
+ result = await self._wrapped.invoke(input_data, context)
113
+
114
+ # 3. Store findings if enabled
115
+ if self._store_findings and self._graph:
116
+ self._store_agent_findings(input_data, result)
117
+
118
+ # 4. Add memory graph metadata
119
+ if "metadata" not in result:
120
+ result["metadata"] = {}
121
+
122
+ result["metadata"]["memory_graph"] = {
123
+ "enabled": self._graph is not None,
124
+ "similar_found": len(context.get("similar_findings", [])),
125
+ "findings_stored": self._store_findings,
126
+ "graph_path": self._graph_path,
127
+ }
128
+
129
+ return result
130
+
131
+ async def stream(self, input_data: str | dict, context: dict | None = None):
132
+ """Stream agent response with memory integration.
133
+
134
+ Note: Memory integration for streaming works at the full response
135
+ level - similar findings are added to context before streaming starts.
136
+ """
137
+ context = context or {}
138
+
139
+ # Query for similar findings
140
+ if self._query_similar and self._graph:
141
+ similar_findings = self._get_similar_findings(input_data)
142
+ if similar_findings:
143
+ context["similar_findings"] = similar_findings
144
+
145
+ # Stream from wrapped agent
146
+ async for chunk in self._wrapped.stream(input_data, context): # type: ignore[attr-defined]
147
+ yield chunk
148
+
149
+ def _get_similar_findings(self, input_data: str | dict) -> list[dict]:
150
+ """Query memory graph for similar past findings."""
151
+ if not self._graph:
152
+ return []
153
+
154
+ try:
155
+ # Build query from input
156
+ if isinstance(input_data, str):
157
+ query = {"name": input_data[:100], "description": input_data}
158
+ else:
159
+ query = {
160
+ "name": str(input_data.get("task", input_data.get("input", "")))[:100],
161
+ "description": str(input_data),
162
+ }
163
+
164
+ # Query graph
165
+ similar = self._graph.find_similar(
166
+ query,
167
+ threshold=self._similarity_threshold,
168
+ limit=self._max_similar_results,
169
+ )
170
+
171
+ # Format results
172
+ results = []
173
+ for node, score in similar:
174
+ if score >= self._similarity_threshold:
175
+ finding = {
176
+ "name": node.name,
177
+ "type": node.type.value if node.type else None,
178
+ "similarity": round(score, 2),
179
+ "source_wizard": node.source_wizard,
180
+ "metadata": node.metadata or {},
181
+ }
182
+
183
+ # Check for resolutions
184
+ resolutions = self._get_resolutions(node.id)
185
+ if resolutions:
186
+ finding["resolutions"] = resolutions
187
+
188
+ results.append(finding)
189
+
190
+ if results:
191
+ logger.debug(f"Found {len(results)} similar findings for agent {self.name}")
192
+
193
+ return results
194
+
195
+ except Exception as e:
196
+ logger.warning(f"Error querying similar findings: {e}")
197
+ return []
198
+
199
+ def _get_resolutions(self, node_id: str) -> list[dict]:
200
+ """Get resolutions (fixes) for a finding."""
201
+ if not self._graph:
202
+ return []
203
+
204
+ try:
205
+ from attune.memory import EdgeType
206
+
207
+ related = self._graph.find_related(node_id, [EdgeType.FIXED_BY])
208
+ return [
209
+ {
210
+ "name": r.name,
211
+ "description": r.metadata.get("description", ""),
212
+ }
213
+ for r in related
214
+ ]
215
+ except Exception: # noqa: BLE001
216
+ # INTENTIONAL: Graceful degradation when graph unavailable
217
+ logger.debug(f"Could not get resolutions for node {node_id}")
218
+ return []
219
+
220
+ def _store_agent_findings(self, input_data: str | dict, result: dict) -> None:
221
+ """Store findings from agent result in memory graph."""
222
+ if not self._graph:
223
+ return
224
+
225
+ try:
226
+ metadata = result.get("metadata", {})
227
+
228
+ # Check for explicit findings in result
229
+ findings = metadata.get("findings", [])
230
+
231
+ # Also check for bug/issue/vulnerability patterns in output
232
+ if not findings and self._contains_finding_patterns(result.get("output", "")):
233
+ # Create implicit finding from result
234
+ if isinstance(input_data, str):
235
+ task_name = input_data[:100]
236
+ else:
237
+ task_name = str(input_data.get("task", input_data.get("input", "")))[:100]
238
+
239
+ findings = [
240
+ {
241
+ "type": self._infer_finding_type(result.get("output", "")),
242
+ "name": f"{self.name}: {task_name}",
243
+ "description": result.get("output", "")[:500],
244
+ },
245
+ ]
246
+
247
+ # Store findings
248
+ for finding in findings:
249
+ finding_id = self._graph.add_finding(self.name, finding)
250
+ logger.debug(f"Stored finding {finding_id} from agent {self.name}")
251
+
252
+ # Save graph
253
+ if findings:
254
+ self._graph._save()
255
+
256
+ except Exception as e:
257
+ logger.warning(f"Error storing findings: {e}")
258
+
259
+ def _contains_finding_patterns(self, text: str) -> bool:
260
+ """Check if output contains patterns indicating a finding."""
261
+ patterns = [
262
+ "found",
263
+ "detected",
264
+ "issue",
265
+ "bug",
266
+ "error",
267
+ "vulnerability",
268
+ "problem",
269
+ "warning",
270
+ "fix",
271
+ ]
272
+ text_lower = text.lower()
273
+ return any(pattern in text_lower for pattern in patterns)
274
+
275
+ def _infer_finding_type(self, text: str) -> str:
276
+ """Infer finding type from output text."""
277
+ text_lower = text.lower()
278
+
279
+ # Check for fix/resolution first (takes precedence)
280
+ if any(x in text_lower for x in ["fix", "fixed", "resolved", "patched"]):
281
+ return "fix"
282
+ if any(x in text_lower for x in ["vulnerability", "security", "injection", "xss"]):
283
+ return "vulnerability"
284
+ if any(x in text_lower for x in ["bug", "error", "exception", "crash"]):
285
+ return "bug"
286
+ if any(x in text_lower for x in ["performance", "slow", "latency", "memory"]):
287
+ return "performance_issue"
288
+ return "pattern"
289
+
290
+ # Delegate other methods to wrapped agent
291
+ def add_tool(self, tool: Any) -> None:
292
+ """Add a tool to the wrapped agent."""
293
+ self._wrapped.add_tool(tool)
294
+
295
+ def get_conversation_history(self) -> list[dict]:
296
+ """Get conversation history from wrapped agent."""
297
+ return self._wrapped.get_conversation_history()
298
+
299
+ def clear_history(self) -> None:
300
+ """Clear conversation history in wrapped agent."""
301
+ self._wrapped.clear_history()
302
+
303
+ @property
304
+ def model(self) -> str:
305
+ """Get the model being used by wrapped agent."""
306
+ return self._wrapped.model
307
+
308
+ @property
309
+ def graph(self):
310
+ """Get the memory graph instance."""
311
+ return self._graph
312
+
313
+ def get_graph_stats(self) -> dict:
314
+ """Get statistics from memory graph."""
315
+ if not self._graph:
316
+ return {"enabled": False}
317
+
318
+ try:
319
+ return {
320
+ "enabled": True,
321
+ "node_count": len(self._graph.nodes),
322
+ "edge_count": len(self._graph.edges),
323
+ "path": str(self._graph.path),
324
+ }
325
+ except Exception as e: # noqa: BLE001
326
+ # INTENTIONAL: Stats are optional, don't crash on errors
327
+ logger.debug(f"Could not get graph stats: {e}")
328
+ return {"enabled": True, "error": "Could not get stats"}