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,264 @@
1
+ """CLI commands for Anthropic Batch API operations (50% cost savings).
2
+
3
+ Provides commands to submit, monitor, and retrieve results from batch processing jobs.
4
+
5
+ Copyright 2025 Smart-AI-Memory
6
+ Licensed under Fair Source License 0.9
7
+ """
8
+
9
+ import asyncio
10
+ import json
11
+ import logging
12
+ import os
13
+ from pathlib import Path
14
+
15
+ from attune.config import _validate_file_path
16
+ from attune.workflows.batch_processing import BatchProcessingWorkflow
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ def cmd_batch_submit(args):
22
+ """Submit a batch processing job from JSON file.
23
+
24
+ Args:
25
+ args: Arguments with input_file path
26
+
27
+ File format:
28
+ [
29
+ {
30
+ "task_id": "task_1",
31
+ "task_type": "analyze_logs",
32
+ "input_data": {"logs": "ERROR: ..."},
33
+ "model_tier": "capable"
34
+ },
35
+ ...
36
+ ]
37
+ """
38
+ input_file = Path(args.input_file)
39
+ if not input_file.exists():
40
+ print(f"āŒ Error: Input file not found: {input_file}")
41
+ return 1
42
+
43
+ print(f"šŸ“¤ Submitting batch from {input_file}...")
44
+
45
+ try:
46
+ # Get API key from environment
47
+ api_key = os.getenv("ANTHROPIC_API_KEY")
48
+ if not api_key:
49
+ print("āŒ Error: ANTHROPIC_API_KEY environment variable not set")
50
+ print(" Set it with: export ANTHROPIC_API_KEY='your-api-key-here'")
51
+ print(" Or get a key from: https://console.anthropic.com/")
52
+ return 1
53
+
54
+ # Load requests from file
55
+ workflow = BatchProcessingWorkflow(api_key=api_key)
56
+ requests = workflow.load_requests_from_file(str(input_file))
57
+
58
+ print(f" Found {len(requests)} requests")
59
+
60
+ # Create batch (sync operation)
61
+ batch_id = workflow.batch_provider.create_batch(
62
+ [
63
+ {
64
+ "custom_id": req.task_id,
65
+ "params": {
66
+ "model": "claude-sonnet-4-5-20250929", # Default model
67
+ "messages": workflow._format_messages(req),
68
+ "max_tokens": 4096,
69
+ },
70
+ }
71
+ for req in requests
72
+ ]
73
+ )
74
+
75
+ print("\nāœ… Batch submitted successfully!")
76
+ print(f" Batch ID: {batch_id}")
77
+ print(f"\nMonitor status with: empathy batch status {batch_id}")
78
+ print(f"Retrieve results with: empathy batch results {batch_id} output.json")
79
+ print(
80
+ f"Or wait for completion: empathy batch wait {batch_id} output.json --poll-interval 300"
81
+ )
82
+
83
+ return 0
84
+
85
+ except Exception as e:
86
+ logger.exception("Failed to submit batch")
87
+ print(f"āŒ Error: {e}")
88
+ return 1
89
+
90
+
91
+ def cmd_batch_status(args):
92
+ """Check status of a batch processing job.
93
+
94
+ Args:
95
+ args: Arguments with batch_id
96
+ """
97
+ batch_id = args.batch_id
98
+
99
+ print(f"šŸ” Checking status for batch {batch_id}...")
100
+
101
+ try:
102
+ api_key = os.getenv("ANTHROPIC_API_KEY")
103
+ if not api_key:
104
+ print("āŒ Error: ANTHROPIC_API_KEY environment variable not set")
105
+ print(" Set it with: export ANTHROPIC_API_KEY='your-api-key-here'")
106
+ print(" Or get a key from: https://console.anthropic.com/")
107
+ return 1
108
+
109
+ workflow = BatchProcessingWorkflow(api_key=api_key)
110
+ status = workflow.batch_provider.get_batch_status(batch_id)
111
+
112
+ print("\nšŸ“Š Batch Status:")
113
+ print(f" ID: {status.id}")
114
+ print(f" Processing Status: {status.processing_status}")
115
+ print(f" Created: {status.created_at}")
116
+
117
+ if hasattr(status, "ended_at") and status.ended_at:
118
+ print(f" Ended: {status.ended_at}")
119
+
120
+ print("\nšŸ“ˆ Request Counts:")
121
+ counts = status.request_counts
122
+ print(f" Processing: {counts.processing}")
123
+ print(f" Succeeded: {counts.succeeded}")
124
+ print(f" Errored: {counts.errored}")
125
+ print(f" Canceled: {counts.canceled}")
126
+ print(f" Expired: {counts.expired}")
127
+
128
+ if status.processing_status == "ended":
129
+ print("\nāœ… Batch processing completed!")
130
+ print(f" Retrieve results with: empathy batch results {batch_id} output.json")
131
+ else:
132
+ print("\nā³ Batch still processing...")
133
+
134
+ # Output JSON if requested
135
+ if args.json:
136
+ print("\n" + json.dumps(status.__dict__, indent=2, default=str))
137
+
138
+ return 0
139
+
140
+ except Exception as e:
141
+ logger.exception("Failed to get batch status")
142
+ print(f"āŒ Error: {e}")
143
+ return 1
144
+
145
+
146
+ def cmd_batch_results(args):
147
+ """Retrieve results from a completed batch.
148
+
149
+ Args:
150
+ args: Arguments with batch_id and output_file
151
+ """
152
+ batch_id = args.batch_id
153
+ output_file = args.output_file
154
+
155
+ print(f"šŸ“„ Retrieving results for batch {batch_id}...")
156
+
157
+ try:
158
+ api_key = os.getenv("ANTHROPIC_API_KEY")
159
+ if not api_key:
160
+ print("āŒ Error: ANTHROPIC_API_KEY environment variable not set")
161
+ print(" Set it with: export ANTHROPIC_API_KEY='your-api-key-here'")
162
+ print(" Or get a key from: https://console.anthropic.com/")
163
+ return 1
164
+
165
+ workflow = BatchProcessingWorkflow(api_key=api_key)
166
+
167
+ # Check status first
168
+ status = workflow.batch_provider.get_batch_status(batch_id)
169
+
170
+ if status.processing_status != "ended":
171
+ print(f"āŒ Error: Batch has not ended processing (status: {status.processing_status})")
172
+ print(f" Wait for completion with: empathy batch wait {batch_id} {output_file}")
173
+ return 1
174
+
175
+ # Get results
176
+ results = workflow.batch_provider.get_batch_results(batch_id)
177
+
178
+ # Save to file
179
+ validated_path = _validate_file_path(output_file)
180
+ with open(validated_path, "w") as f:
181
+ json.dump([dict(r) for r in results], f, indent=2, default=str)
182
+
183
+ print(f"\nāœ… Results saved to {validated_path}")
184
+ print(f" Total: {len(results)} results")
185
+
186
+ # Summary
187
+ succeeded = sum(
188
+ 1 for r in results if r.get("result", {}).get("type") == "succeeded"
189
+ )
190
+ errored = sum(
191
+ 1 for r in results if r.get("result", {}).get("type") == "errored"
192
+ )
193
+
194
+ print(f" Succeeded: {succeeded}")
195
+ print(f" Errored: {errored}")
196
+
197
+ return 0
198
+
199
+ except Exception as e:
200
+ logger.exception("Failed to retrieve results")
201
+ print(f"āŒ Error: {e}")
202
+ return 1
203
+
204
+
205
+ def cmd_batch_wait(args):
206
+ """Wait for batch to complete and retrieve results.
207
+
208
+ Args:
209
+ args: Arguments with batch_id, output_file, poll_interval, timeout
210
+ """
211
+ batch_id = args.batch_id
212
+ output_file = args.output_file
213
+ poll_interval = args.poll_interval
214
+ timeout = args.timeout
215
+
216
+ print(f"ā³ Waiting for batch {batch_id} to complete...")
217
+ print(f" Polling every {poll_interval}s (max {timeout}s)")
218
+
219
+ try:
220
+ api_key = os.getenv("ANTHROPIC_API_KEY")
221
+ if not api_key:
222
+ print("āŒ Error: ANTHROPIC_API_KEY environment variable not set")
223
+ print(" Set it with: export ANTHROPIC_API_KEY='your-api-key-here'")
224
+ print(" Or get a key from: https://console.anthropic.com/")
225
+ return 1
226
+
227
+ workflow = BatchProcessingWorkflow(api_key=api_key)
228
+
229
+ # Wait for completion (async)
230
+ results = asyncio.run(
231
+ workflow.batch_provider.wait_for_batch(
232
+ batch_id, poll_interval=poll_interval, timeout=timeout
233
+ )
234
+ )
235
+
236
+ # Save results
237
+ validated_path = _validate_file_path(output_file)
238
+ with open(validated_path, "w") as f:
239
+ json.dump([dict(r) for r in results], f, indent=2, default=str)
240
+
241
+ print(f"\nāœ… Batch completed! Results saved to {validated_path}")
242
+ print(f" Total: {len(results)} results")
243
+
244
+ # Summary
245
+ succeeded = sum(
246
+ 1 for r in results if r.get("result", {}).get("type") == "succeeded"
247
+ )
248
+ errored = sum(
249
+ 1 for r in results if r.get("result", {}).get("type") == "errored"
250
+ )
251
+
252
+ print(f" Succeeded: {succeeded}")
253
+ print(f" Errored: {errored}")
254
+
255
+ return 0
256
+
257
+ except TimeoutError:
258
+ print(f"\nā° Timeout: Batch did not complete within {timeout}s")
259
+ print(f" Check status with: empathy batch status {batch_id}")
260
+ return 1
261
+ except Exception as e:
262
+ logger.exception("Failed to wait for batch")
263
+ print(f"āŒ Error: {e}")
264
+ return 1
@@ -0,0 +1,248 @@
1
+ """Cache monitoring and statistics commands for the CLI.
2
+
3
+ Copyright 2025 Smart-AI-Memory
4
+ Licensed under Fair Source License 0.9
5
+ """
6
+
7
+ import json
8
+ import re
9
+ from datetime import datetime, timedelta
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+
14
+ def cmd_cache_stats(args):
15
+ """Display prompt caching statistics and savings.
16
+
17
+ Analyzes logs and telemetry to show cache performance metrics:
18
+ - Cache hit rate
19
+ - Total cost savings
20
+ - Cache read/write tokens
21
+ - Recommendations for optimization
22
+
23
+ Args:
24
+ args: Namespace object from argparse with attributes:
25
+ - days (int): Number of days to analyze (default: 7)
26
+ - format (str): Output format ('table' or 'json')
27
+ - verbose (bool): Show detailed breakdown
28
+
29
+ Returns:
30
+ None: Prints cache statistics report or JSON output
31
+ """
32
+ print(f"\nšŸ” Analyzing cache performance (last {args.days} days)...\n")
33
+
34
+ # Collect cache metrics from logs
35
+ stats = _collect_cache_stats(days=args.days)
36
+
37
+ if args.format == "json":
38
+ print(json.dumps(stats, indent=2))
39
+ return
40
+
41
+ # Display formatted report
42
+ _display_cache_report(stats, verbose=args.verbose)
43
+
44
+
45
+ def _collect_cache_stats(days: int = 7) -> dict[str, Any]:
46
+ """Collect cache statistics from logs and telemetry.
47
+
48
+ Args:
49
+ days: Number of days to analyze
50
+
51
+ Returns:
52
+ Dictionary with cache statistics
53
+ """
54
+ # Try to find log files
55
+ log_paths = [
56
+ Path.cwd() / "attune.log",
57
+ Path.home() / ".empathy" / "logs" / "attune.log",
58
+ Path("/tmp/attune.log"),
59
+ ]
60
+
61
+ log_file = None
62
+ for path in log_paths:
63
+ if path.exists():
64
+ log_file = path
65
+ break
66
+
67
+ if not log_file:
68
+ return {
69
+ "error": "No log file found",
70
+ "message": "Enable logging to track cache performance",
71
+ "total_requests": 0,
72
+ "cache_hits": 0,
73
+ "cache_writes": 0,
74
+ "total_savings": 0.0,
75
+ }
76
+
77
+ # Parse log file for cache metrics
78
+ cutoff_date = datetime.now() - timedelta(days=days)
79
+
80
+ cache_hits = 0
81
+ cache_writes = 0
82
+ total_cache_read_tokens = 0
83
+ total_cache_write_tokens = 0
84
+ total_savings = 0.0
85
+ total_requests = 0
86
+
87
+ # Regex patterns for log parsing
88
+ cache_hit_pattern = re.compile(r"Cache HIT: ([\d,]+) tokens read.*saved \$([\d.]+)")
89
+ cache_write_pattern = re.compile(r"Cache WRITE: ([\d,]+) tokens written.*cost \$([\d.]+)")
90
+
91
+ try:
92
+ with open(log_file) as f:
93
+ for line in f:
94
+ # Try to extract timestamp
95
+ # Common format: 2026-01-27 21:30:45,123
96
+ timestamp_match = re.match(
97
+ r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})", line
98
+ )
99
+ if timestamp_match:
100
+ try:
101
+ log_time = datetime.strptime(
102
+ timestamp_match.group(1), "%Y-%m-%d %H:%M:%S"
103
+ )
104
+ if log_time < cutoff_date:
105
+ continue # Skip old entries
106
+ except ValueError:
107
+ pass # Continue if timestamp parsing fails
108
+
109
+ # Count API requests (approximate)
110
+ if "anthropic.AsyncAnthropic" in line or "messages.create" in line:
111
+ total_requests += 1
112
+
113
+ # Parse cache hit
114
+ hit_match = cache_hit_pattern.search(line)
115
+ if hit_match:
116
+ tokens_str = hit_match.group(1).replace(",", "")
117
+ tokens = int(tokens_str)
118
+ savings = float(hit_match.group(2))
119
+
120
+ cache_hits += 1
121
+ total_cache_read_tokens += tokens
122
+ total_savings += savings
123
+
124
+ # Parse cache write
125
+ write_match = cache_write_pattern.search(line)
126
+ if write_match:
127
+ tokens_str = write_match.group(1).replace(",", "")
128
+ tokens = int(tokens_str)
129
+
130
+ cache_writes += 1
131
+ total_cache_write_tokens += tokens
132
+
133
+ except Exception as e:
134
+ return {
135
+ "error": f"Failed to parse log file: {e}",
136
+ "total_requests": 0,
137
+ "cache_hits": 0,
138
+ "cache_writes": 0,
139
+ "total_savings": 0.0,
140
+ }
141
+
142
+ # Calculate metrics
143
+ cache_hit_rate = (
144
+ (cache_hits / total_requests * 100) if total_requests > 0 else 0.0
145
+ )
146
+
147
+ return {
148
+ "days_analyzed": days,
149
+ "log_file": str(log_file),
150
+ "total_requests": total_requests,
151
+ "cache_hits": cache_hits,
152
+ "cache_writes": cache_writes,
153
+ "cache_hit_rate": round(cache_hit_rate, 1),
154
+ "total_cache_read_tokens": total_cache_read_tokens,
155
+ "total_cache_write_tokens": total_cache_write_tokens,
156
+ "total_savings": round(total_savings, 4),
157
+ "avg_savings_per_hit": (
158
+ round(total_savings / cache_hits, 4) if cache_hits > 0 else 0.0
159
+ ),
160
+ }
161
+
162
+
163
+ def _display_cache_report(stats: dict[str, Any], verbose: bool = False):
164
+ """Display formatted cache statistics report.
165
+
166
+ Args:
167
+ stats: Cache statistics dictionary
168
+ verbose: Show detailed breakdown
169
+ """
170
+ # Handle error cases
171
+ if "error" in stats:
172
+ print(f"āš ļø {stats['error']}")
173
+ if "message" in stats:
174
+ print(f" {stats['message']}")
175
+ return
176
+
177
+ # Summary section
178
+ print("=" * 60)
179
+ print("PROMPT CACHING PERFORMANCE SUMMARY")
180
+ print("=" * 60)
181
+ print(f"Analysis Period: Last {stats['days_analyzed']} days")
182
+ print(f"Log File: {stats['log_file']}")
183
+ print()
184
+
185
+ # Key metrics
186
+ print("šŸ“Š Key Metrics:")
187
+ print(f" Total API Requests: {stats['total_requests']:,}")
188
+ print(f" Cache Hits: {stats['cache_hits']:,}")
189
+ print(f" Cache Writes: {stats['cache_writes']:,}")
190
+ print(f" Cache Hit Rate: {stats['cache_hit_rate']}%")
191
+ print()
192
+
193
+ # Cost savings
194
+ print("šŸ’° Cost Savings:")
195
+ print(f" Total Saved: ${stats['total_savings']:.4f}")
196
+ if stats['cache_hits'] > 0:
197
+ print(f" Avg Savings per Hit: ${stats['avg_savings_per_hit']:.4f}")
198
+ print()
199
+
200
+ # Token metrics (verbose mode)
201
+ if verbose:
202
+ print("šŸ”¢ Token Metrics:")
203
+ print(f" Cache Read Tokens: {stats['total_cache_read_tokens']:,}")
204
+ print(f" Cache Write Tokens: {stats['total_cache_write_tokens']:,}")
205
+ print()
206
+
207
+ # Performance assessment
208
+ hit_rate = stats['cache_hit_rate']
209
+ print("šŸ“ˆ Performance Assessment:")
210
+ if hit_rate >= 50:
211
+ print(" āœ… EXCELLENT - Cache is working effectively")
212
+ print(" Your workflows are benefiting from prompt caching")
213
+ elif hit_rate >= 30:
214
+ print(" āœ“ GOOD - Cache is providing moderate benefits")
215
+ print(" Consider structuring prompts for better cache reuse")
216
+ elif hit_rate >= 10:
217
+ print(" āš ļø LOW - Cache hit rate could be improved")
218
+ print(" Review your workflow patterns for optimization")
219
+ else:
220
+ print(" āŒ VERY LOW - Cache is not being utilized effectively")
221
+ print(" Consider enabling prompt caching or restructuring prompts")
222
+ print()
223
+
224
+ # Recommendations
225
+ if stats['total_requests'] < 10:
226
+ print("ā„¹ļø Note: Limited data available. Run more workflows for accurate stats.")
227
+ elif hit_rate < 30:
228
+ print("šŸ’” Recommendations:")
229
+ print(" 1. Reuse system prompts across workflow steps")
230
+ print(" 2. Structure large context (docs, code) for caching")
231
+ print(" 3. Cache TTL is 5 minutes - batch related requests")
232
+ print(" 4. Enable use_prompt_caching=True in AnthropicProvider")
233
+
234
+ print("=" * 60)
235
+
236
+
237
+ def cmd_cache_clear(args):
238
+ """Clear cached data (placeholder for future implementation).
239
+
240
+ Args:
241
+ args: Namespace object from argparse
242
+
243
+ Returns:
244
+ None: Prints status message
245
+ """
246
+ print("\nāš ļø Cache clearing not implemented.")
247
+ print("Anthropic's cache has a 5-minute TTL and is server-side.")
248
+ print("Wait 5 minutes for cache to expire naturally.\n")