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.
- attune/__init__.py +358 -0
- attune/adaptive/__init__.py +13 -0
- attune/adaptive/task_complexity.py +127 -0
- attune/agent_monitoring.py +414 -0
- attune/cache/__init__.py +117 -0
- attune/cache/base.py +166 -0
- attune/cache/dependency_manager.py +256 -0
- attune/cache/hash_only.py +251 -0
- attune/cache/hybrid.py +457 -0
- attune/cache/storage.py +285 -0
- attune/cache_monitor.py +356 -0
- attune/cache_stats.py +298 -0
- attune/cli/__init__.py +152 -0
- attune/cli/__main__.py +12 -0
- attune/cli/commands/__init__.py +1 -0
- attune/cli/commands/batch.py +264 -0
- attune/cli/commands/cache.py +248 -0
- attune/cli/commands/help.py +331 -0
- attune/cli/commands/info.py +140 -0
- attune/cli/commands/inspect.py +436 -0
- attune/cli/commands/inspection.py +57 -0
- attune/cli/commands/memory.py +48 -0
- attune/cli/commands/metrics.py +92 -0
- attune/cli/commands/orchestrate.py +184 -0
- attune/cli/commands/patterns.py +207 -0
- attune/cli/commands/profiling.py +202 -0
- attune/cli/commands/provider.py +98 -0
- attune/cli/commands/routing.py +285 -0
- attune/cli/commands/setup.py +96 -0
- attune/cli/commands/status.py +235 -0
- attune/cli/commands/sync.py +166 -0
- attune/cli/commands/tier.py +121 -0
- attune/cli/commands/utilities.py +114 -0
- attune/cli/commands/workflow.py +579 -0
- attune/cli/core.py +32 -0
- attune/cli/parsers/__init__.py +68 -0
- attune/cli/parsers/batch.py +118 -0
- attune/cli/parsers/cache.py +65 -0
- attune/cli/parsers/help.py +41 -0
- attune/cli/parsers/info.py +26 -0
- attune/cli/parsers/inspect.py +66 -0
- attune/cli/parsers/metrics.py +42 -0
- attune/cli/parsers/orchestrate.py +61 -0
- attune/cli/parsers/patterns.py +54 -0
- attune/cli/parsers/provider.py +40 -0
- attune/cli/parsers/routing.py +110 -0
- attune/cli/parsers/setup.py +42 -0
- attune/cli/parsers/status.py +47 -0
- attune/cli/parsers/sync.py +31 -0
- attune/cli/parsers/tier.py +33 -0
- attune/cli/parsers/workflow.py +77 -0
- attune/cli/utils/__init__.py +1 -0
- attune/cli/utils/data.py +242 -0
- attune/cli/utils/helpers.py +68 -0
- attune/cli_legacy.py +3957 -0
- attune/cli_minimal.py +1159 -0
- attune/cli_router.py +437 -0
- attune/cli_unified.py +814 -0
- attune/config/__init__.py +66 -0
- attune/config/xml_config.py +286 -0
- attune/config.py +545 -0
- attune/coordination.py +870 -0
- attune/core.py +1511 -0
- attune/core_modules/__init__.py +15 -0
- attune/cost_tracker.py +626 -0
- attune/dashboard/__init__.py +41 -0
- attune/dashboard/app.py +512 -0
- attune/dashboard/simple_server.py +435 -0
- attune/dashboard/standalone_server.py +547 -0
- attune/discovery.py +306 -0
- attune/emergence.py +306 -0
- attune/exceptions.py +123 -0
- attune/feedback_loops.py +373 -0
- attune/hot_reload/README.md +473 -0
- attune/hot_reload/__init__.py +62 -0
- attune/hot_reload/config.py +83 -0
- attune/hot_reload/integration.py +229 -0
- attune/hot_reload/reloader.py +298 -0
- attune/hot_reload/watcher.py +183 -0
- attune/hot_reload/websocket.py +177 -0
- attune/levels.py +577 -0
- attune/leverage_points.py +441 -0
- attune/logging_config.py +261 -0
- attune/mcp/__init__.py +10 -0
- attune/mcp/server.py +506 -0
- attune/memory/__init__.py +237 -0
- attune/memory/claude_memory.py +469 -0
- attune/memory/config.py +224 -0
- attune/memory/control_panel.py +1290 -0
- attune/memory/control_panel_support.py +145 -0
- attune/memory/cross_session.py +845 -0
- attune/memory/edges.py +179 -0
- attune/memory/encryption.py +159 -0
- attune/memory/file_session.py +770 -0
- attune/memory/graph.py +570 -0
- attune/memory/long_term.py +913 -0
- attune/memory/long_term_types.py +99 -0
- attune/memory/mixins/__init__.py +25 -0
- attune/memory/mixins/backend_init_mixin.py +249 -0
- attune/memory/mixins/capabilities_mixin.py +208 -0
- attune/memory/mixins/handoff_mixin.py +208 -0
- attune/memory/mixins/lifecycle_mixin.py +49 -0
- attune/memory/mixins/long_term_mixin.py +352 -0
- attune/memory/mixins/promotion_mixin.py +109 -0
- attune/memory/mixins/short_term_mixin.py +182 -0
- attune/memory/nodes.py +179 -0
- attune/memory/redis_bootstrap.py +540 -0
- attune/memory/security/__init__.py +31 -0
- attune/memory/security/audit_logger.py +932 -0
- attune/memory/security/pii_scrubber.py +640 -0
- attune/memory/security/secrets_detector.py +678 -0
- attune/memory/short_term.py +2192 -0
- attune/memory/simple_storage.py +302 -0
- attune/memory/storage/__init__.py +15 -0
- attune/memory/storage_backend.py +167 -0
- attune/memory/summary_index.py +583 -0
- attune/memory/types.py +446 -0
- attune/memory/unified.py +182 -0
- attune/meta_workflows/__init__.py +74 -0
- attune/meta_workflows/agent_creator.py +248 -0
- attune/meta_workflows/builtin_templates.py +567 -0
- attune/meta_workflows/cli_commands/__init__.py +56 -0
- attune/meta_workflows/cli_commands/agent_commands.py +321 -0
- attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
- attune/meta_workflows/cli_commands/config_commands.py +232 -0
- attune/meta_workflows/cli_commands/memory_commands.py +182 -0
- attune/meta_workflows/cli_commands/template_commands.py +354 -0
- attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
- attune/meta_workflows/cli_meta_workflows.py +59 -0
- attune/meta_workflows/form_engine.py +292 -0
- attune/meta_workflows/intent_detector.py +409 -0
- attune/meta_workflows/models.py +569 -0
- attune/meta_workflows/pattern_learner.py +738 -0
- attune/meta_workflows/plan_generator.py +384 -0
- attune/meta_workflows/session_context.py +397 -0
- attune/meta_workflows/template_registry.py +229 -0
- attune/meta_workflows/workflow.py +984 -0
- attune/metrics/__init__.py +12 -0
- attune/metrics/collector.py +31 -0
- attune/metrics/prompt_metrics.py +194 -0
- attune/models/__init__.py +172 -0
- attune/models/__main__.py +13 -0
- attune/models/adaptive_routing.py +437 -0
- attune/models/auth_cli.py +444 -0
- attune/models/auth_strategy.py +450 -0
- attune/models/cli.py +655 -0
- attune/models/empathy_executor.py +354 -0
- attune/models/executor.py +257 -0
- attune/models/fallback.py +762 -0
- attune/models/provider_config.py +282 -0
- attune/models/registry.py +472 -0
- attune/models/tasks.py +359 -0
- attune/models/telemetry/__init__.py +71 -0
- attune/models/telemetry/analytics.py +594 -0
- attune/models/telemetry/backend.py +196 -0
- attune/models/telemetry/data_models.py +431 -0
- attune/models/telemetry/storage.py +489 -0
- attune/models/token_estimator.py +420 -0
- attune/models/validation.py +280 -0
- attune/monitoring/__init__.py +52 -0
- attune/monitoring/alerts.py +946 -0
- attune/monitoring/alerts_cli.py +448 -0
- attune/monitoring/multi_backend.py +271 -0
- attune/monitoring/otel_backend.py +362 -0
- attune/optimization/__init__.py +19 -0
- attune/optimization/context_optimizer.py +272 -0
- attune/orchestration/__init__.py +67 -0
- attune/orchestration/agent_templates.py +707 -0
- attune/orchestration/config_store.py +499 -0
- attune/orchestration/execution_strategies.py +2111 -0
- attune/orchestration/meta_orchestrator.py +1168 -0
- attune/orchestration/pattern_learner.py +696 -0
- attune/orchestration/real_tools.py +931 -0
- attune/pattern_cache.py +187 -0
- attune/pattern_library.py +542 -0
- attune/patterns/debugging/all_patterns.json +81 -0
- attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
- attune/patterns/refactoring_memory.json +89 -0
- attune/persistence.py +564 -0
- attune/platform_utils.py +265 -0
- attune/plugins/__init__.py +28 -0
- attune/plugins/base.py +361 -0
- attune/plugins/registry.py +268 -0
- attune/project_index/__init__.py +32 -0
- attune/project_index/cli.py +335 -0
- attune/project_index/index.py +667 -0
- attune/project_index/models.py +504 -0
- attune/project_index/reports.py +474 -0
- attune/project_index/scanner.py +777 -0
- attune/project_index/scanner_parallel.py +291 -0
- attune/prompts/__init__.py +61 -0
- attune/prompts/config.py +77 -0
- attune/prompts/context.py +177 -0
- attune/prompts/parser.py +285 -0
- attune/prompts/registry.py +313 -0
- attune/prompts/templates.py +208 -0
- attune/redis_config.py +302 -0
- attune/redis_memory.py +799 -0
- attune/resilience/__init__.py +56 -0
- attune/resilience/circuit_breaker.py +256 -0
- attune/resilience/fallback.py +179 -0
- attune/resilience/health.py +300 -0
- attune/resilience/retry.py +209 -0
- attune/resilience/timeout.py +135 -0
- attune/routing/__init__.py +43 -0
- attune/routing/chain_executor.py +433 -0
- attune/routing/classifier.py +217 -0
- attune/routing/smart_router.py +234 -0
- attune/routing/workflow_registry.py +343 -0
- attune/scaffolding/README.md +589 -0
- attune/scaffolding/__init__.py +35 -0
- attune/scaffolding/__main__.py +14 -0
- attune/scaffolding/cli.py +240 -0
- attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
- attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
- attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
- attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
- attune/socratic/__init__.py +256 -0
- attune/socratic/ab_testing.py +958 -0
- attune/socratic/blueprint.py +533 -0
- attune/socratic/cli.py +703 -0
- attune/socratic/collaboration.py +1114 -0
- attune/socratic/domain_templates.py +924 -0
- attune/socratic/embeddings.py +738 -0
- attune/socratic/engine.py +794 -0
- attune/socratic/explainer.py +682 -0
- attune/socratic/feedback.py +772 -0
- attune/socratic/forms.py +629 -0
- attune/socratic/generator.py +732 -0
- attune/socratic/llm_analyzer.py +637 -0
- attune/socratic/mcp_server.py +702 -0
- attune/socratic/session.py +312 -0
- attune/socratic/storage.py +667 -0
- attune/socratic/success.py +730 -0
- attune/socratic/visual_editor.py +860 -0
- attune/socratic/web_ui.py +958 -0
- attune/telemetry/__init__.py +39 -0
- attune/telemetry/agent_coordination.py +475 -0
- attune/telemetry/agent_tracking.py +367 -0
- attune/telemetry/approval_gates.py +545 -0
- attune/telemetry/cli.py +1231 -0
- attune/telemetry/commands/__init__.py +14 -0
- attune/telemetry/commands/dashboard_commands.py +696 -0
- attune/telemetry/event_streaming.py +409 -0
- attune/telemetry/feedback_loop.py +567 -0
- attune/telemetry/usage_tracker.py +591 -0
- attune/templates.py +754 -0
- attune/test_generator/__init__.py +38 -0
- attune/test_generator/__main__.py +14 -0
- attune/test_generator/cli.py +234 -0
- attune/test_generator/generator.py +355 -0
- attune/test_generator/risk_analyzer.py +216 -0
- attune/test_generator/templates/unit_test.py.jinja2 +272 -0
- attune/tier_recommender.py +384 -0
- attune/tools.py +183 -0
- attune/trust/__init__.py +28 -0
- attune/trust/circuit_breaker.py +579 -0
- attune/trust_building.py +527 -0
- attune/validation/__init__.py +19 -0
- attune/validation/xml_validator.py +281 -0
- attune/vscode_bridge.py +173 -0
- attune/workflow_commands.py +780 -0
- attune/workflow_patterns/__init__.py +33 -0
- attune/workflow_patterns/behavior.py +249 -0
- attune/workflow_patterns/core.py +76 -0
- attune/workflow_patterns/output.py +99 -0
- attune/workflow_patterns/registry.py +255 -0
- attune/workflow_patterns/structural.py +288 -0
- attune/workflows/__init__.py +539 -0
- attune/workflows/autonomous_test_gen.py +1268 -0
- attune/workflows/base.py +2667 -0
- attune/workflows/batch_processing.py +342 -0
- attune/workflows/bug_predict.py +1084 -0
- attune/workflows/builder.py +273 -0
- attune/workflows/caching.py +253 -0
- attune/workflows/code_review.py +1048 -0
- attune/workflows/code_review_adapters.py +312 -0
- attune/workflows/code_review_pipeline.py +722 -0
- attune/workflows/config.py +645 -0
- attune/workflows/dependency_check.py +644 -0
- attune/workflows/document_gen/__init__.py +25 -0
- attune/workflows/document_gen/config.py +30 -0
- attune/workflows/document_gen/report_formatter.py +162 -0
- attune/workflows/document_gen/workflow.py +1426 -0
- attune/workflows/document_manager.py +216 -0
- attune/workflows/document_manager_README.md +134 -0
- attune/workflows/documentation_orchestrator.py +1205 -0
- attune/workflows/history.py +510 -0
- attune/workflows/keyboard_shortcuts/__init__.py +39 -0
- attune/workflows/keyboard_shortcuts/generators.py +391 -0
- attune/workflows/keyboard_shortcuts/parsers.py +416 -0
- attune/workflows/keyboard_shortcuts/prompts.py +295 -0
- attune/workflows/keyboard_shortcuts/schema.py +193 -0
- attune/workflows/keyboard_shortcuts/workflow.py +509 -0
- attune/workflows/llm_base.py +363 -0
- attune/workflows/manage_docs.py +87 -0
- attune/workflows/manage_docs_README.md +134 -0
- attune/workflows/manage_documentation.py +821 -0
- attune/workflows/new_sample_workflow1.py +149 -0
- attune/workflows/new_sample_workflow1_README.md +150 -0
- attune/workflows/orchestrated_health_check.py +849 -0
- attune/workflows/orchestrated_release_prep.py +600 -0
- attune/workflows/output.py +413 -0
- attune/workflows/perf_audit.py +863 -0
- attune/workflows/pr_review.py +762 -0
- attune/workflows/progress.py +785 -0
- attune/workflows/progress_server.py +322 -0
- attune/workflows/progressive/README 2.md +454 -0
- attune/workflows/progressive/README.md +454 -0
- attune/workflows/progressive/__init__.py +82 -0
- attune/workflows/progressive/cli.py +219 -0
- attune/workflows/progressive/core.py +488 -0
- attune/workflows/progressive/orchestrator.py +723 -0
- attune/workflows/progressive/reports.py +520 -0
- attune/workflows/progressive/telemetry.py +274 -0
- attune/workflows/progressive/test_gen.py +495 -0
- attune/workflows/progressive/workflow.py +589 -0
- attune/workflows/refactor_plan.py +694 -0
- attune/workflows/release_prep.py +895 -0
- attune/workflows/release_prep_crew.py +969 -0
- attune/workflows/research_synthesis.py +404 -0
- attune/workflows/routing.py +168 -0
- attune/workflows/secure_release.py +593 -0
- attune/workflows/security_adapters.py +297 -0
- attune/workflows/security_audit.py +1329 -0
- attune/workflows/security_audit_phase3.py +355 -0
- attune/workflows/seo_optimization.py +633 -0
- attune/workflows/step_config.py +234 -0
- attune/workflows/telemetry_mixin.py +269 -0
- attune/workflows/test5.py +125 -0
- attune/workflows/test5_README.md +158 -0
- attune/workflows/test_coverage_boost_crew.py +849 -0
- attune/workflows/test_gen/__init__.py +52 -0
- attune/workflows/test_gen/ast_analyzer.py +249 -0
- attune/workflows/test_gen/config.py +88 -0
- attune/workflows/test_gen/data_models.py +38 -0
- attune/workflows/test_gen/report_formatter.py +289 -0
- attune/workflows/test_gen/test_templates.py +381 -0
- attune/workflows/test_gen/workflow.py +655 -0
- attune/workflows/test_gen.py +54 -0
- attune/workflows/test_gen_behavioral.py +477 -0
- attune/workflows/test_gen_parallel.py +341 -0
- attune/workflows/test_lifecycle.py +526 -0
- attune/workflows/test_maintenance.py +627 -0
- attune/workflows/test_maintenance_cli.py +590 -0
- attune/workflows/test_maintenance_crew.py +840 -0
- attune/workflows/test_runner.py +622 -0
- attune/workflows/tier_tracking.py +531 -0
- attune/workflows/xml_enhanced_crew.py +285 -0
- attune_ai-2.0.0.dist-info/METADATA +1026 -0
- attune_ai-2.0.0.dist-info/RECORD +457 -0
- attune_ai-2.0.0.dist-info/WHEEL +5 -0
- attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
- attune_ai-2.0.0.dist-info/top_level.txt +5 -0
- attune_healthcare/__init__.py +13 -0
- attune_healthcare/monitors/__init__.py +9 -0
- attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
- attune_healthcare/monitors/monitoring/__init__.py +44 -0
- attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
- attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
- attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
- attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
- attune_llm/README.md +553 -0
- attune_llm/__init__.py +28 -0
- attune_llm/agent_factory/__init__.py +53 -0
- attune_llm/agent_factory/adapters/__init__.py +85 -0
- attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
- attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
- attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
- attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
- attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
- attune_llm/agent_factory/adapters/native.py +228 -0
- attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
- attune_llm/agent_factory/base.py +305 -0
- attune_llm/agent_factory/crews/__init__.py +67 -0
- attune_llm/agent_factory/crews/code_review.py +1113 -0
- attune_llm/agent_factory/crews/health_check.py +1262 -0
- attune_llm/agent_factory/crews/refactoring.py +1128 -0
- attune_llm/agent_factory/crews/security_audit.py +1018 -0
- attune_llm/agent_factory/decorators.py +287 -0
- attune_llm/agent_factory/factory.py +558 -0
- attune_llm/agent_factory/framework.py +193 -0
- attune_llm/agent_factory/memory_integration.py +328 -0
- attune_llm/agent_factory/resilient.py +320 -0
- attune_llm/agents_md/__init__.py +22 -0
- attune_llm/agents_md/loader.py +218 -0
- attune_llm/agents_md/parser.py +271 -0
- attune_llm/agents_md/registry.py +307 -0
- attune_llm/claude_memory.py +466 -0
- attune_llm/cli/__init__.py +8 -0
- attune_llm/cli/sync_claude.py +487 -0
- attune_llm/code_health.py +1313 -0
- attune_llm/commands/__init__.py +51 -0
- attune_llm/commands/context.py +375 -0
- attune_llm/commands/loader.py +301 -0
- attune_llm/commands/models.py +231 -0
- attune_llm/commands/parser.py +371 -0
- attune_llm/commands/registry.py +429 -0
- attune_llm/config/__init__.py +29 -0
- attune_llm/config/unified.py +291 -0
- attune_llm/context/__init__.py +22 -0
- attune_llm/context/compaction.py +455 -0
- attune_llm/context/manager.py +434 -0
- attune_llm/contextual_patterns.py +361 -0
- attune_llm/core.py +907 -0
- attune_llm/git_pattern_extractor.py +435 -0
- attune_llm/hooks/__init__.py +24 -0
- attune_llm/hooks/config.py +306 -0
- attune_llm/hooks/executor.py +289 -0
- attune_llm/hooks/registry.py +302 -0
- attune_llm/hooks/scripts/__init__.py +39 -0
- attune_llm/hooks/scripts/evaluate_session.py +201 -0
- attune_llm/hooks/scripts/first_time_init.py +285 -0
- attune_llm/hooks/scripts/pre_compact.py +207 -0
- attune_llm/hooks/scripts/session_end.py +183 -0
- attune_llm/hooks/scripts/session_start.py +163 -0
- attune_llm/hooks/scripts/suggest_compact.py +225 -0
- attune_llm/learning/__init__.py +30 -0
- attune_llm/learning/evaluator.py +438 -0
- attune_llm/learning/extractor.py +514 -0
- attune_llm/learning/storage.py +560 -0
- attune_llm/levels.py +227 -0
- attune_llm/pattern_confidence.py +414 -0
- attune_llm/pattern_resolver.py +272 -0
- attune_llm/pattern_summary.py +350 -0
- attune_llm/providers.py +967 -0
- attune_llm/routing/__init__.py +32 -0
- attune_llm/routing/model_router.py +362 -0
- attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
- attune_llm/security/PHASE2_COMPLETE.md +384 -0
- attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- attune_llm/security/QUICK_REFERENCE.md +316 -0
- attune_llm/security/README.md +262 -0
- attune_llm/security/__init__.py +62 -0
- attune_llm/security/audit_logger.py +929 -0
- attune_llm/security/audit_logger_example.py +152 -0
- attune_llm/security/pii_scrubber.py +640 -0
- attune_llm/security/secrets_detector.py +678 -0
- attune_llm/security/secrets_detector_example.py +304 -0
- attune_llm/security/secure_memdocs.py +1192 -0
- attune_llm/security/secure_memdocs_example.py +278 -0
- attune_llm/session_status.py +745 -0
- attune_llm/state.py +246 -0
- attune_llm/utils/__init__.py +5 -0
- attune_llm/utils/tokens.py +349 -0
- attune_software/SOFTWARE_PLUGIN_README.md +57 -0
- attune_software/__init__.py +13 -0
- attune_software/cli/__init__.py +120 -0
- attune_software/cli/inspect.py +362 -0
- attune_software/cli.py +574 -0
- attune_software/plugin.py +188 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- 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")
|