aria-code 0.167.0__py3-none-win_amd64.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.
- aria_bots/__init__.py +7 -0
- aria_bots/channels/README.md +97 -0
- aria_bots/channels/__init__.py +1 -0
- aria_bots/channels/approvals.py +263 -0
- aria_bots/channels/conversation.py +280 -0
- aria_bots/channels/digest.py +186 -0
- aria_bots/channels/registry.py +95 -0
- aria_bots/engine.py +144 -0
- aria_bots/feishu_bot.py +1385 -0
- aria_bots/logistics/__init__.py +1 -0
- aria_bots/logistics/carriers.py +253 -0
- aria_bots/logistics/freight.py +154 -0
- aria_bots/logistics/inventory.py +242 -0
- aria_bots/logistics/mcp_server.py +156 -0
- aria_bots/logistics/records.py +119 -0
- aria_bots/logistics/tenancy.py +152 -0
- aria_bots/market.py +91 -0
- aria_bots/relay_client.py +326 -0
- aria_bots/telegram_bot.py +299 -0
- aria_code/__init__.py +111 -0
- aria_code/_bin/aria-native.exe +0 -0
- aria_code/_bin/aria-runtime.exe +0 -0
- aria_code/_version.py +20 -0
- aria_code/account_memory.py +296 -0
- aria_code/account_session.py +166 -0
- aria_code/adk_apps/__init__.py +1 -0
- aria_code/adk_apps/aria_code_review/__init__.py +1 -0
- aria_code/adk_apps/aria_code_review/agent.py +32 -0
- aria_code/adk_apps/aria_research/__init__.py +1 -0
- aria_code/adk_apps/aria_research/agent.py +31 -0
- aria_code/agents/__init__.py +49 -0
- aria_code/agents/base.py +329 -0
- aria_code/agents/code_review.py +200 -0
- aria_code/agents/deep/__init__.py +37 -0
- aria_code/agents/deep/calibration_loop.py +144 -0
- aria_code/agents/deep/critic.py +125 -0
- aria_code/agents/deep/deepen.py +193 -0
- aria_code/agents/deep/models.py +149 -0
- aria_code/agents/deep/pipeline.py +164 -0
- aria_code/agents/deep/quant_fusion.py +192 -0
- aria_code/agents/deep/themes.py +95 -0
- aria_code/agents/deep/tiers.py +106 -0
- aria_code/agents/engineering/__init__.py +14 -0
- aria_code/agents/engineering/coder.py +222 -0
- aria_code/agents/engineering/tester.py +145 -0
- aria_code/agents/financial/__init__.py +21 -0
- aria_code/agents/financial/cashflow_burn.py +119 -0
- aria_code/agents/financial/catalyst.py +279 -0
- aria_code/agents/financial/corporate_finance.py +175 -0
- aria_code/agents/financial/debate.py +224 -0
- aria_code/agents/financial/earnings.py +315 -0
- aria_code/agents/financial/fundamental.py +178 -0
- aria_code/agents/financial/macro.py +111 -0
- aria_code/agents/financial/news.py +231 -0
- aria_code/agents/financial/risk.py +146 -0
- aria_code/agents/financial/sector.py +279 -0
- aria_code/agents/financial/strategist.py +121 -0
- aria_code/agents/financial/stripe_revenue.py +127 -0
- aria_code/agents/financial/synthesis.py +274 -0
- aria_code/agents/financial/technical.py +277 -0
- aria_code/agents/orchestrator.py +44 -0
- aria_code/agents/portfolio_agent.py +392 -0
- aria_code/agents/realty/__init__.py +62 -0
- aria_code/agents/realty/asset_diagnosis.py +152 -0
- aria_code/agents/realty/business_match.py +166 -0
- aria_code/agents/realty/cashflow_verify.py +209 -0
- aria_code/agents/realty/contract_rules.py +210 -0
- aria_code/agents/realty/energy_anomaly.py +189 -0
- aria_code/agents/realty/exit_settlement.py +208 -0
- aria_code/agents/realty/fulfillment_risk.py +206 -0
- aria_code/agents/realty/ops_optimize.py +160 -0
- aria_code/agents/realty/revenue_share.py +215 -0
- aria_code/agents/registry.py +168 -0
- aria_code/agents/signal_scheme.py +111 -0
- aria_code/agents/sports/__init__.py +0 -0
- aria_code/agents/sports/football_agent.py +197 -0
- aria_code/agents/supervisor.py +113 -0
- aria_code/agents/team.py +500 -0
- aria_code/agents/video/__init__.py +16 -0
- aria_code/agents/video/director.py +376 -0
- aria_code/agents/video/qa_agent.py +143 -0
- aria_code/agents/video/script_doctor.py +112 -0
- aria_code/agents/warehouse/__init__.py +25 -0
- aria_code/agents/warehouse/contracts.py +26 -0
- aria_code/agents/warehouse/dashboard.py +155 -0
- aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
- aria_code/agents/warehouse/inbound_exceptions.py +25 -0
- aria_code/agents/warehouse/inventory_health.py +24 -0
- aria_code/agents/warehouse/local_run.py +71 -0
- aria_code/agents/warehouse/local_snapshot.py +132 -0
- aria_code/agents/warehouse/logistics_cost.py +84 -0
- aria_code/agents/warehouse/logistics_sync.py +21 -0
- aria_code/agents/warehouse/navigation.schema.json +110 -0
- aria_code/agents/warehouse/task_agent.py +172 -0
- aria_code/agents/warehouse/workflow.py +31 -0
- aria_code/aliyun_data_client.py +4 -0
- aria_code/apps/README.md +12 -0
- aria_code/apps/__init__.py +2 -0
- aria_code/apps/channels/README.md +9 -0
- aria_code/apps/channels/__init__.py +17 -0
- aria_code/apps/channels/approvals.py +11 -0
- aria_code/apps/channels/conversation.py +11 -0
- aria_code/apps/channels/digest.py +11 -0
- aria_code/apps/channels/intake.py +92 -0
- aria_code/apps/channels/registry.py +11 -0
- aria_code/apps/channels/tradingview.py +94 -0
- aria_code/apps/cli/README.md +13 -0
- aria_code/apps/cli/__init__.py +2 -0
- aria_code/apps/cli/_optional.py +120 -0
- aria_code/apps/cli/app_server.py +656 -0
- aria_code/apps/cli/auto_update.py +125 -0
- aria_code/apps/cli/bootstrap.py +206 -0
- aria_code/apps/cli/broker_render.py +206 -0
- aria_code/apps/cli/chat_turn.py +1327 -0
- aria_code/apps/cli/cloud_models.py +231 -0
- aria_code/apps/cli/codegen_paths.py +29 -0
- aria_code/apps/cli/commands/__init__.py +34 -0
- aria_code/apps/cli/commands/_business_render.py +78 -0
- aria_code/apps/cli/commands/_ui.py +71 -0
- aria_code/apps/cli/commands/analysis_cmds.py +378 -0
- aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
- aria_code/apps/cli/commands/auth_cmds.py +215 -0
- aria_code/apps/cli/commands/backtest_cmds.py +2518 -0
- aria_code/apps/cli/commands/broker_cmds.py +1236 -0
- aria_code/apps/cli/commands/business_workflow_cmds.py +379 -0
- aria_code/apps/cli/commands/canvas_cmds.py +77 -0
- aria_code/apps/cli/commands/catalog.py +189 -0
- aria_code/apps/cli/commands/core_cmds.py +2748 -0
- aria_code/apps/cli/commands/data_cmds.py +521 -0
- aria_code/apps/cli/commands/diagnostic_cmds.py +285 -0
- aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
- aria_code/apps/cli/commands/engineering_cmds.py +399 -0
- aria_code/apps/cli/commands/file_cmds.py +312 -0
- aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
- aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
- aria_code/apps/cli/commands/market.py +544 -0
- aria_code/apps/cli/commands/market_cmds.py +1419 -0
- aria_code/apps/cli/commands/market_context.py +432 -0
- aria_code/apps/cli/commands/market_render.py +7 -0
- aria_code/apps/cli/commands/model_cmds.py +2374 -0
- aria_code/apps/cli/commands/ops_cmds.py +721 -0
- aria_code/apps/cli/commands/orchestrator_cmds.py +181 -0
- aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
- aria_code/apps/cli/commands/portfolio_cmds.py +1316 -0
- aria_code/apps/cli/commands/report.py +476 -0
- aria_code/apps/cli/commands/scaffold_templates.py +617 -0
- aria_code/apps/cli/commands/session_cmds.py +236 -0
- aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
- aria_code/apps/cli/commands/team.py +723 -0
- aria_code/apps/cli/commands/team_render.py +8 -0
- aria_code/apps/cli/commands/ui_cmds.py +401 -0
- aria_code/apps/cli/commands/warehouse_cmds.py +297 -0
- aria_code/apps/cli/commands/workflow_cmds.py +629 -0
- aria_code/apps/cli/commands/workspace_cmds.py +1543 -0
- aria_code/apps/cli/config_paths.py +73 -0
- aria_code/apps/cli/config_store.py +158 -0
- aria_code/apps/cli/constants.py +88 -0
- aria_code/apps/cli/context.py +34 -0
- aria_code/apps/cli/conversation_policy.py +53 -0
- aria_code/apps/cli/deterministic.py +200 -0
- aria_code/apps/cli/direct.py +48 -0
- aria_code/apps/cli/earnings_view.py +172 -0
- aria_code/apps/cli/endpoint_migration.py +64 -0
- aria_code/apps/cli/exec_events.py +255 -0
- aria_code/apps/cli/file_references.py +155 -0
- aria_code/apps/cli/finance_service_catalog.py +111 -0
- aria_code/apps/cli/football_reports.py +231 -0
- aria_code/apps/cli/github_app_auth.py +135 -0
- aria_code/apps/cli/google_login.py +239 -0
- aria_code/apps/cli/handlers/__init__.py +11 -0
- aria_code/apps/cli/handlers/broker_handlers.py +122 -0
- aria_code/apps/cli/handlers/chart_handlers.py +1314 -0
- aria_code/apps/cli/handlers/market_handlers.py +2570 -0
- aria_code/apps/cli/handlers/realty_handlers.py +114 -0
- aria_code/apps/cli/handlers/sports_handlers.py +22 -0
- aria_code/apps/cli/handlers/strategy_advice.py +82 -0
- aria_code/apps/cli/headless.py +352 -0
- aria_code/apps/cli/helpers.py +326 -0
- aria_code/apps/cli/hooks.py +180 -0
- aria_code/apps/cli/i18n.py +310 -0
- aria_code/apps/cli/intent.py +136 -0
- aria_code/apps/cli/intent_router.py +305 -0
- aria_code/apps/cli/intent_shadow.py +72 -0
- aria_code/apps/cli/intent_signals.py +347 -0
- aria_code/apps/cli/lifecycle_hooks.py +48 -0
- aria_code/apps/cli/local_tool_schemas.py +550 -0
- aria_code/apps/cli/main.py +39 -0
- aria_code/apps/cli/market_hours.py +100 -0
- aria_code/apps/cli/market_metadata.py +135 -0
- aria_code/apps/cli/market_universe.py +487 -0
- aria_code/apps/cli/message_processing.py +310 -0
- aria_code/apps/cli/mixin_binding.py +32 -0
- aria_code/apps/cli/model_catalog.py +652 -0
- aria_code/apps/cli/model_probe.py +169 -0
- aria_code/apps/cli/model_retirement.py +65 -0
- aria_code/apps/cli/native_branding.py +12 -0
- aria_code/apps/cli/native_bridge.py +118 -0
- aria_code/apps/cli/native_entry.py +58 -0
- aria_code/apps/cli/pdf_report.py +977 -0
- aria_code/apps/cli/plan_mode.py +139 -0
- aria_code/apps/cli/plotly_html.py +15 -0
- aria_code/apps/cli/prediction_feedback.py +202 -0
- aria_code/apps/cli/preflight.py +502 -0
- aria_code/apps/cli/project_aria.py +60 -0
- aria_code/apps/cli/prompt_assembly.py +78 -0
- aria_code/apps/cli/prompts/__init__.py +0 -0
- aria_code/apps/cli/prompts/coding.py +71 -0
- aria_code/apps/cli/prompts/select.py +193 -0
- aria_code/apps/cli/prompts/system_prompts.py +562 -0
- aria_code/apps/cli/prompts/ui.py +436 -0
- aria_code/apps/cli/provider_endpoints.py +237 -0
- aria_code/apps/cli/provider_keys.py +73 -0
- aria_code/apps/cli/providers/__init__.py +1 -0
- aria_code/apps/cli/providers/base.py +775 -0
- aria_code/apps/cli/providers/chat_routing.py +139 -0
- aria_code/apps/cli/providers/collaboration.py +98 -0
- aria_code/apps/cli/providers/llm/__init__.py +1 -0
- aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
- aria_code/apps/cli/providers/llm/ollama_stream.py +1574 -0
- aria_code/apps/cli/providers/llm/response_cache.py +60 -0
- aria_code/apps/cli/providers/llm/sse_stream.py +298 -0
- aria_code/apps/cli/providers/runtime_bridge.py +586 -0
- aria_code/apps/cli/providers/vertexai_stream.py +592 -0
- aria_code/apps/cli/release_download.py +159 -0
- aria_code/apps/cli/review_runner.py +111 -0
- aria_code/apps/cli/runtime_consumer.py +769 -0
- aria_code/apps/cli/sandbox.py +32 -0
- aria_code/apps/cli/session_export.py +120 -0
- aria_code/apps/cli/session_jsonl.py +208 -0
- aria_code/apps/cli/session_refresh.py +123 -0
- aria_code/apps/cli/session_store.py +125 -0
- aria_code/apps/cli/skills_catalog.py +273 -0
- aria_code/apps/cli/task_isolation.py +211 -0
- aria_code/apps/cli/terminal_chrome.py +412 -0
- aria_code/apps/cli/todo_tracker.py +190 -0
- aria_code/apps/cli/tool_executor.py +932 -0
- aria_code/apps/cli/tool_registry.py +34 -0
- aria_code/apps/cli/tool_scope.py +113 -0
- aria_code/apps/cli/tools/__init__.py +40 -0
- aria_code/apps/cli/tools/context.py +46 -0
- aria_code/apps/cli/tools/file_tools.py +181 -0
- aria_code/apps/cli/tools/market_tools.py +626 -0
- aria_code/apps/cli/tools/notebook_tools.py +111 -0
- aria_code/apps/cli/tools/system_tools.py +656 -0
- aria_code/apps/cli/tools/write_tools.py +961 -0
- aria_code/apps/cli/tradingview_bridge.py +529 -0
- aria_code/apps/cli/transactions.py +269 -0
- aria_code/apps/cli/turn_planning.py +137 -0
- aria_code/apps/cli/update_check.py +257 -0
- aria_code/apps/cli/updater.py +373 -0
- aria_code/apps/cli/utils/__init__.py +0 -0
- aria_code/apps/cli/utils/market_detect.py +1663 -0
- aria_code/apps/cli/web_login.py +136 -0
- aria_code/apps/cli/workflow_runner.py +127 -0
- aria_code/apps/cli/workspace_route.py +121 -0
- aria_code/apps/daemon/README.md +14 -0
- aria_code/apps/vscode/README.md +115 -0
- aria_code/apps/vscode/package.json +70 -0
- aria_code/aria_cli.py +5244 -0
- aria_code/aria_daemon.py +1372 -0
- aria_code/aria_feishu_bot.py +16 -0
- aria_code/aria_mcp_server.py +61 -0
- aria_code/aria_relay_client.py +4 -0
- aria_code/aria_telegram_bot.py +11 -0
- aria_code/ariarc.py +385 -0
- aria_code/artifacts.py +581 -0
- aria_code/backtest_engine.py +4 -0
- aria_code/backtest_report.py +4 -0
- aria_code/brokers/__init__.py +78 -0
- aria_code/brokers/automation.py +193 -0
- aria_code/brokers/base.py +231 -0
- aria_code/brokers/capabilities.py +264 -0
- aria_code/brokers/cn/__init__.py +10 -0
- aria_code/brokers/cn/easytrader_broker.py +193 -0
- aria_code/brokers/cn/futu_broker.py +194 -0
- aria_code/brokers/cn/longbridge_broker.py +190 -0
- aria_code/brokers/cn/tiger_broker.py +196 -0
- aria_code/brokers/cn/xtquant_broker.py +225 -0
- aria_code/brokers/config.py +414 -0
- aria_code/brokers/intl/__init__.py +5 -0
- aria_code/brokers/intl/alpaca_broker.py +183 -0
- aria_code/brokers/intl/ibkr_broker.py +215 -0
- aria_code/brokers/intl/trading212_broker.py +183 -0
- aria_code/brokers/intl/webull_broker.py +156 -0
- aria_code/brokers/paper_broker.py +266 -0
- aria_code/brokers/planning.py +296 -0
- aria_code/brokers/registry.py +213 -0
- aria_code/brokers/trading.py +267 -0
- aria_code/canva_client.py +4 -0
- aria_code/change_store.py +127 -0
- aria_code/clients/__init__.py +0 -0
- aria_code/clients/aliyun_data_client.py +660 -0
- aria_code/clients/aria_relay_client.py +16 -0
- aria_code/clients/canva_client.py +284 -0
- aria_code/clients/figma_client.py +100 -0
- aria_code/clients/football_data_client.py +1671 -0
- aria_code/clients/kling_video_client.py +182 -0
- aria_code/clients/market_data_client.py +1985 -0
- aria_code/clients/openai_image_client.py +242 -0
- aria_code/clients/runway_video_client.py +157 -0
- aria_code/clients/warehouse_erp_client.py +105 -0
- aria_code/cloud_memory.py +190 -0
- aria_code/command_safety.py +19 -0
- aria_code/computer_use_server.py +276 -0
- aria_code/computer_use_tools.py +4 -0
- aria_code/dashboard_generator.py +579 -0
- aria_code/data_analysis_tools.py +4 -0
- aria_code/data_cleaner.py +483 -0
- aria_code/data_service.py +513 -0
- aria_code/datasources/__init__.py +23 -0
- aria_code/datasources/base.py +166 -0
- aria_code/datasources/router.py +253 -0
- aria_code/datasources/sec_statements.py +217 -0
- aria_code/datasources/sources/__init__.py +15 -0
- aria_code/datasources/sources/akshare_source.py +269 -0
- aria_code/datasources/sources/alpha_vantage_source.py +203 -0
- aria_code/datasources/sources/edgar_source.py +219 -0
- aria_code/datasources/sources/finnhub_source.py +198 -0
- aria_code/datasources/sources/fred_source.py +223 -0
- aria_code/datasources/sources/tushare_source.py +143 -0
- aria_code/datasources/sources/web_scraper_source.py +278 -0
- aria_code/datasources/sources/world_bank_source.py +206 -0
- aria_code/datasources/sources/yfinance_source.py +152 -0
- aria_code/doctor.py +860 -0
- aria_code/domain/__init__.py +0 -0
- aria_code/domain/_finance_core/__init__.py +5 -0
- aria_code/domain/_finance_core/backtest_engine.py +325 -0
- aria_code/domain/_finance_core/performance_stats.py +101 -0
- aria_code/domain/backtest_engine.py +75 -0
- aria_code/domain/backtest_report.py +488 -0
- aria_code/domain/finance_formulas.py +389 -0
- aria_code/domain/performance_stats.py +6 -0
- aria_code/domain/portfolio_ledger.py +307 -0
- aria_code/domain/strategy_vault.py +421 -0
- aria_code/evals/__init__.py +37 -0
- aria_code/evals/behavior.py +113 -0
- aria_code/evals/gap.py +93 -0
- aria_code/evals/harness.py +949 -0
- aria_code/evals/review_probe.py +132 -0
- aria_code/evals/runner.py +425 -0
- aria_code/evals/scorecard.py +322 -0
- aria_code/evals/summary.py +125 -0
- aria_code/external_agent_runner.py +115 -0
- aria_code/figma_client.py +4 -0
- aria_code/file_analysis_tools.py +4 -0
- aria_code/finance_formulas.py +4 -0
- aria_code/football_data_client.py +4 -0
- aria_code/image_gen_tools.py +4 -0
- aria_code/intent_classifier.py +459 -0
- aria_code/kling_video_client.py +4 -0
- aria_code/licensing.py +151 -0
- aria_code/local_finance_tools.py +4 -0
- aria_code/local_image_provider.py +4 -0
- aria_code/local_llm_provider.py +4 -0
- aria_code/macro_tools.py +4 -0
- aria_code/markdown_pdf.py +289 -0
- aria_code/market_data_client.py +4 -0
- aria_code/mcp_client.py +744 -0
- aria_code/memory_manager.py +273 -0
- aria_code/model_capability.py +512 -0
- aria_code/notification_tools.py +4 -0
- aria_code/openai_image_client.py +4 -0
- aria_code/packages/__init__.py +26 -0
- aria_code/packages/adk_bridge/__init__.py +11 -0
- aria_code/packages/adk_bridge/code_review_tools.py +49 -0
- aria_code/packages/adk_bridge/market_tools.py +125 -0
- aria_code/packages/aria_agents/__init__.py +5 -0
- aria_code/packages/aria_agents/manifest.py +78 -0
- aria_code/packages/aria_core/__init__.py +34 -0
- aria_code/packages/aria_core/architecture.py +269 -0
- aria_code/packages/aria_core/export.py +147 -0
- aria_code/packages/aria_core/manifest.py +65 -0
- aria_code/packages/aria_core/paths.py +57 -0
- aria_code/packages/aria_core/secure_file.py +68 -0
- aria_code/packages/aria_infra/__init__.py +15 -0
- aria_code/packages/aria_infra/arthera.py +58 -0
- aria_code/packages/aria_infra/doctor.py +246 -0
- aria_code/packages/aria_infra/product.py +40 -0
- aria_code/packages/aria_mcp/__init__.py +25 -0
- aria_code/packages/aria_mcp/bridge.py +232 -0
- aria_code/packages/aria_mcp/circuit.py +82 -0
- aria_code/packages/aria_mcp/config.py +162 -0
- aria_code/packages/aria_mcp/installer.py +95 -0
- aria_code/packages/aria_mcp/server.py +1705 -0
- aria_code/packages/aria_mcp/tools.py +81 -0
- aria_code/packages/aria_sdk/__init__.py +19 -0
- aria_code/packages/aria_sdk/client.py +393 -0
- aria_code/packages/aria_sdk/providers.py +70 -0
- aria_code/packages/aria_sdk/streaming.py +75 -0
- aria_code/packages/aria_sdk/types.py +86 -0
- aria_code/packages/aria_services/__init__.py +92 -0
- aria_code/packages/aria_services/cache.py +60 -0
- aria_code/packages/aria_services/context.py +356 -0
- aria_code/packages/aria_services/context_checkpoints.py +157 -0
- aria_code/packages/aria_services/data.py +11 -0
- aria_code/packages/aria_services/provider_health.py +304 -0
- aria_code/packages/aria_services/references.py +247 -0
- aria_code/packages/aria_services/registry.py +249 -0
- aria_code/packages/aria_services/research_protocol.py +137 -0
- aria_code/packages/aria_services/research_quality.py +186 -0
- aria_code/packages/aria_services/settings.py +160 -0
- aria_code/packages/aria_services/usage.py +151 -0
- aria_code/packages/aria_skills/__init__.py +46 -0
- aria_code/packages/aria_skills/catalog.py +149 -0
- aria_code/packages/aria_skills/loader.py +455 -0
- aria_code/packages/aria_skills/registry.py +84 -0
- aria_code/packages/aria_tools/__init__.py +5 -0
- aria_code/packages/aria_tools/financial/__init__.py +5 -0
- aria_code/packages/aria_tools/financial/_paths.py +92 -0
- aria_code/packages/aria_tools/registry.py +129 -0
- aria_code/packages/quant_engine/__init__.py +33 -0
- aria_code/packages/quant_engine/_namespace.py +24 -0
- aria_code/packages/quant_engine/backtest/__init__.py +10 -0
- aria_code/packages/quant_engine/backtest/core.py +53 -0
- aria_code/packages/quant_engine/backtest/engine.py +102 -0
- aria_code/packages/quant_engine/portfolio/__init__.py +9 -0
- aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
- aria_code/packages/quant_engine/sports/__init__.py +76 -0
- aria_code/packages/quant_engine/sports/calibrator.py +354 -0
- aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
- aria_code/packages/quant_engine/sports/elo.py +300 -0
- aria_code/packages/quant_engine/sports/form.py +188 -0
- aria_code/packages/quant_engine/sports/h2h.py +195 -0
- aria_code/packages/quant_engine/sports/predictor.py +312 -0
- aria_code/packages/quant_engine/sports/tracker.py +665 -0
- aria_code/packages/quant_engine/stochastic/__init__.py +31 -0
- aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
- aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
- aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
- aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
- aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
- aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
- aria_code/packs/__init__.py +85 -0
- aria_code/packs/base.py +168 -0
- aria_code/packs/finance/__init__.py +250 -0
- aria_code/packs/healthcare/__init__.py +40 -0
- aria_code/packs/logistics/__init__.py +171 -0
- aria_code/packs/payments/__init__.py +139 -0
- aria_code/packs/realty/__init__.py +190 -0
- aria_code/packs/registry.py +202 -0
- aria_code/packs/rules.py +90 -0
- aria_code/plan_utils.py +194 -0
- aria_code/plugin_loader.py +328 -0
- aria_code/portfolio_ledger.py +4 -0
- aria_code/preview_server.py +449 -0
- aria_code/privacy/__init__.py +5 -0
- aria_code/privacy/feedback.py +123 -0
- aria_code/project_review.py +278 -0
- aria_code/project_review_api.py +235 -0
- aria_code/project_review_server.py +18 -0
- aria_code/project_tools.py +4 -0
- aria_code/providers/__init__.py +30 -0
- aria_code/providers/google_video_provider.py +256 -0
- aria_code/providers/llm/__init__.py +19 -0
- aria_code/providers/llm/anthropic.py +184 -0
- aria_code/providers/llm/arthera_gateway.py +90 -0
- aria_code/providers/llm/autoconfig.py +213 -0
- aria_code/providers/llm/base.py +139 -0
- aria_code/providers/llm/custom.py +158 -0
- aria_code/providers/llm/ollama.py +137 -0
- aria_code/providers/llm/openai_compat.py +350 -0
- aria_code/providers/llm/registry.py +457 -0
- aria_code/providers/local_image_provider.py +202 -0
- aria_code/providers/local_llm_provider.py +549 -0
- aria_code/providers/ollama_models.py +79 -0
- aria_code/providers/openai_params.py +32 -0
- aria_code/providers/tool_messages.py +100 -0
- aria_code/realty_data_tools.py +4 -0
- aria_code/report_exporters.py +150 -0
- aria_code/report_generator.py +1764 -0
- aria_code/review_service.py +497 -0
- aria_code/runtime/__init__.py +176 -0
- aria_code/runtime/acceptance.py +632 -0
- aria_code/runtime/agent_loop.py +1851 -0
- aria_code/runtime/agent_profiles.py +75 -0
- aria_code/runtime/approval.py +71 -0
- aria_code/runtime/baseline.py +219 -0
- aria_code/runtime/budget.py +232 -0
- aria_code/runtime/checkpoints.py +481 -0
- aria_code/runtime/consult.py +65 -0
- aria_code/runtime/contract.py +282 -0
- aria_code/runtime/delivery.py +432 -0
- aria_code/runtime/events.py +113 -0
- aria_code/runtime/gateway.py +167 -0
- aria_code/runtime/lsp.py +484 -0
- aria_code/runtime/native_index.py +153 -0
- aria_code/runtime/orchestrator.py +55 -0
- aria_code/runtime/processes.py +343 -0
- aria_code/runtime/project_graph.py +614 -0
- aria_code/runtime/repo_map.py +712 -0
- aria_code/runtime/research_bundle.py +105 -0
- aria_code/runtime/review.py +269 -0
- aria_code/runtime/run_state.py +127 -0
- aria_code/runtime/run_store.py +522 -0
- aria_code/runtime/scoped_runs.py +113 -0
- aria_code/runtime/self_healing.py +422 -0
- aria_code/runtime/semantic_diff.py +171 -0
- aria_code/runtime/subagent.py +721 -0
- aria_code/runtime/symbol_edit.py +117 -0
- aria_code/runtime/task_brief.py +46 -0
- aria_code/runtime/task_context.py +145 -0
- aria_code/runtime/task_ledger.py +108 -0
- aria_code/runtime/task_orchestrator.py +90 -0
- aria_code/runtime/task_outcome.py +33 -0
- aria_code/runtime/task_verification.py +266 -0
- aria_code/runtime/task_worktree.py +448 -0
- aria_code/runtime/tool_executor.py +329 -0
- aria_code/runtime/tool_policy.py +107 -0
- aria_code/runtime/transactions.py +216 -0
- aria_code/runtime/windows_job.py +115 -0
- aria_code/runtime/workflows.py +222 -0
- aria_code/runtime/worktrees.py +215 -0
- aria_code/runway_video_client.py +4 -0
- aria_code/safety/__init__.py +27 -0
- aria_code/safety/client_isolation.py +178 -0
- aria_code/safety/permissions.py +339 -0
- aria_code/safety/risk.py +699 -0
- aria_code/safety/sandbox.py +148 -0
- aria_code/safety/service.py +102 -0
- aria_code/service_endpoints.py +14 -0
- aria_code/setup_wizard.py +684 -0
- aria_code/spreadsheet_tools.py +4 -0
- aria_code/strategy_vault.py +4 -0
- aria_code/tools/__init__.py +0 -0
- aria_code/tools/artifact_tools.py +252 -0
- aria_code/tools/broker_tools.py +92 -0
- aria_code/tools/build_quant_engine.py +97 -0
- aria_code/tools/code_audit_tools.py +192 -0
- aria_code/tools/computer_use_tools.py +509 -0
- aria_code/tools/data_analysis_tools.py +831 -0
- aria_code/tools/enterprise_finance_tools.py +202 -0
- aria_code/tools/extended_tools.py +240 -0
- aria_code/tools/file_analysis_tools.py +880 -0
- aria_code/tools/image_gen_tools.py +114 -0
- aria_code/tools/local_finance_tools.py +3488 -0
- aria_code/tools/logistics_carriers.py +11 -0
- aria_code/tools/logistics_inventory.py +11 -0
- aria_code/tools/logistics_io.py +11 -0
- aria_code/tools/logistics_tenancy.py +11 -0
- aria_code/tools/logistics_tools.py +11 -0
- aria_code/tools/macro_tools.py +412 -0
- aria_code/tools/notification_tools.py +249 -0
- aria_code/tools/project_tools.py +525 -0
- aria_code/tools/realty_data_tools.py +662 -0
- aria_code/tools/spreadsheet_tools.py +399 -0
- aria_code/tools/stripe_tools.py +115 -0
- aria_code/tools/video_tools.py +500 -0
- aria_code/training/__init__.py +1 -0
- aria_code/training/compare.py +117 -0
- aria_code/training/prelude_commands.py +111 -0
- aria_code/training/prelude_eval.py +390 -0
- aria_code/training/prelude_real.py +183 -0
- aria_code/training/prelude_train.py +248 -0
- aria_code/training/sft_dataset.py +230 -0
- aria_code/training/trajectory_dataset.py +263 -0
- aria_code/ui/__init__.py +105 -0
- aria_code/ui/banner.py +404 -0
- aria_code/ui/completer.py +571 -0
- aria_code/ui/console.py +285 -0
- aria_code/ui/input_box.py +505 -0
- aria_code/ui/mentions.py +206 -0
- aria_code/ui/picker.py +248 -0
- aria_code/ui/render/__init__.py +11 -0
- aria_code/ui/render/actions.py +297 -0
- aria_code/ui/render/finance.py +1732 -0
- aria_code/ui/render/market.py +253 -0
- aria_code/ui/render/output.py +954 -0
- aria_code/ui/render/responsive.py +75 -0
- aria_code/ui/render/team.py +367 -0
- aria_code/ui/robot.py +239 -0
- aria_code/ui/startup_dashboard.py +110 -0
- aria_code/video_analysis.py +147 -0
- aria_code/video_editor.py +518 -0
- aria_code/video_workflow/__init__.py +8 -0
- aria_code/video_workflow/__main__.py +61 -0
- aria_code/video_workflow/engines/__init__.py +18 -0
- aria_code/video_workflow/engines/base.py +69 -0
- aria_code/video_workflow/engines/custom_model.py +204 -0
- aria_code/video_workflow/engines/google_veo.py +94 -0
- aria_code/video_workflow/engines/local_engine.py +71 -0
- aria_code/video_workflow/engines/registry.py +98 -0
- aria_code/video_workflow/google_models.py +278 -0
- aria_code/video_workflow/music/__init__.py +5 -0
- aria_code/video_workflow/music/foley_service.py +132 -0
- aria_code/video_workflow/music/service.py +212 -0
- aria_code/video_workflow/pipeline.py +620 -0
- aria_code/video_workflow/plan.py +202 -0
- aria_code/video_workflow/session.py +297 -0
- aria_code/workspace/__init__.py +6 -0
- aria_code/workspace/files.py +219 -0
- aria_code/workspace/verify.py +167 -0
- aria_code/workspace_changes.py +199 -0
- aria_code/workspace_service.py +196 -0
- aria_code/workspace_tools.py +150 -0
- aria_code-0.167.0.dist-info/METADATA +330 -0
- aria_code-0.167.0.dist-info/RECORD +601 -0
- aria_code-0.167.0.dist-info/WHEEL +5 -0
- aria_code-0.167.0.dist-info/entry_points.txt +5 -0
- aria_code-0.167.0.dist-info/licenses/LICENSE +201 -0
- aria_code-0.167.0.dist-info/licenses/NOTICE +49 -0
- aria_code-0.167.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"""The REPL's transaction points: take one before each turn, rewind to any.
|
|
2
|
+
|
|
3
|
+
``runtime/transactions.py`` stores points; this reads and writes the state a
|
|
4
|
+
point covers, which lives in the terminal and in CLI module globals:
|
|
5
|
+
|
|
6
|
+
* the conversation — ``terminal.conversation``;
|
|
7
|
+
* approvals — ``_auto_approve_session``, ``_session_always_allow`` and
|
|
8
|
+
``_session_command_prefixes`` in the module the terminal was built in
|
|
9
|
+
(aria_cli rebinds the approval functions onto its own globals, so that copy
|
|
10
|
+
is the one in force, not tool_executor's);
|
|
11
|
+
* the task list — ``aria_code.apps.cli.todo_tracker``, the copy the
|
|
12
|
+
``update_todos`` tool writes;
|
|
13
|
+
* background tasks — ``runtime.subagent``, the copy the CLI registers;
|
|
14
|
+
* the task worktree — ``apps.cli.task_isolation``.
|
|
15
|
+
|
|
16
|
+
Files are undone first: a conflict there stops the rewind before anything
|
|
17
|
+
else has changed.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import logging
|
|
23
|
+
import sys
|
|
24
|
+
import time
|
|
25
|
+
from dataclasses import dataclass, field
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Any, Optional
|
|
28
|
+
|
|
29
|
+
from aria_code.runtime.transactions import (
|
|
30
|
+
TransactionPoint,
|
|
31
|
+
TransactionStore,
|
|
32
|
+
default_transaction_store,
|
|
33
|
+
new_point,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
_STORE: list[Optional[TransactionStore]] = [None]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def store() -> TransactionStore:
|
|
42
|
+
if _STORE[0] is None:
|
|
43
|
+
_STORE[0] = default_transaction_store()
|
|
44
|
+
return _STORE[0]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def reset_for_tests(replacement: Any = None) -> None:
|
|
48
|
+
_STORE[0] = replacement
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _namespace(terminal: Any) -> dict:
|
|
52
|
+
return vars(sys.modules[type(terminal).__module__])
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _todos():
|
|
56
|
+
from aria_code.apps.cli import todo_tracker
|
|
57
|
+
return todo_tracker
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _checkpoints():
|
|
61
|
+
# The aria_code.* copy, as the write tools record with: a conflict raised
|
|
62
|
+
# from it is the class callers catch.
|
|
63
|
+
from aria_code.runtime.checkpoints import CheckpointStore
|
|
64
|
+
return CheckpointStore()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _approvals(namespace: dict) -> dict:
|
|
68
|
+
return {
|
|
69
|
+
"allow_all": bool(namespace.get("_auto_approve_session", False)),
|
|
70
|
+
"tools": sorted(namespace.get("_session_always_allow") or ()),
|
|
71
|
+
"prefixes": sorted(list(prefix) for prefix in namespace.get("_session_command_prefixes") or ()),
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _open_task(terminal: Any) -> Optional[dict]:
|
|
76
|
+
try:
|
|
77
|
+
from apps.cli import task_isolation
|
|
78
|
+
|
|
79
|
+
tasks = task_isolation.manager()
|
|
80
|
+
task = tasks.active(task_isolation._workspace(terminal.config))
|
|
81
|
+
if task is None:
|
|
82
|
+
return None
|
|
83
|
+
return {"task_id": task.task_id, "repository": task.repository, "path": task.path,
|
|
84
|
+
"patch": tasks.patch(task)}
|
|
85
|
+
except Exception as exc:
|
|
86
|
+
logger.debug("task state not captured: %s", exc)
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def capture(terminal: Any, prompt: str) -> Optional[TransactionPoint]:
|
|
91
|
+
"""Record the state before the turn ``prompt`` starts. Never raises."""
|
|
92
|
+
try:
|
|
93
|
+
session_id = str(getattr(terminal, "session_id", "") or "default")
|
|
94
|
+
turn = sum(1 for message in terminal.conversation if message.get("role") == "user") + 1
|
|
95
|
+
point = new_point(
|
|
96
|
+
session_id=session_id, turn=turn, prompt=prompt,
|
|
97
|
+
messages=list(terminal.conversation),
|
|
98
|
+
todos=list(_todos().get_active_todos()),
|
|
99
|
+
approvals=_approvals(_namespace(terminal)),
|
|
100
|
+
checkpoint_sequence=_checkpoints().max_sequence(),
|
|
101
|
+
verdict=str(getattr(terminal, "_code_verdict", "") or ""),
|
|
102
|
+
task=_open_task(terminal),
|
|
103
|
+
)
|
|
104
|
+
return store().record(point)
|
|
105
|
+
except Exception as exc:
|
|
106
|
+
logger.debug("transaction point not recorded: %s", exc)
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class RewindOutcome:
|
|
112
|
+
point: TransactionPoint
|
|
113
|
+
restored_paths: tuple = ()
|
|
114
|
+
messages_removed: int = 0
|
|
115
|
+
approvals_revoked: list = field(default_factory=list)
|
|
116
|
+
tasks_cancelled: list = field(default_factory=list)
|
|
117
|
+
task_note: str = ""
|
|
118
|
+
|
|
119
|
+
def lines(self) -> list[str]:
|
|
120
|
+
count = len(self.restored_paths)
|
|
121
|
+
out = [f"Rewound to before turn {self.point.turn}: “{self.point.prompt}”"]
|
|
122
|
+
out.append(f" files {count} restored" if count else " files no changes to undo")
|
|
123
|
+
out.append(f" conversation {self.messages_removed} message{'s' if self.messages_removed != 1 else ''} removed")
|
|
124
|
+
if self.approvals_revoked:
|
|
125
|
+
out.append(f" approvals revoked {', '.join(self.approvals_revoked)}")
|
|
126
|
+
if self.tasks_cancelled:
|
|
127
|
+
out.append(f" background cancelled {', '.join(self.tasks_cancelled)}")
|
|
128
|
+
if self.task_note:
|
|
129
|
+
out.append(f" task {self.task_note}")
|
|
130
|
+
if self.point.verdict:
|
|
131
|
+
out.append(f" checks {self.point.verdict} at this point")
|
|
132
|
+
if self.point.truncated:
|
|
133
|
+
out.append(" note the oldest messages were too large to keep and are not restored")
|
|
134
|
+
return out
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _worktree_skip(terminal: Any):
|
|
138
|
+
"""Files in task worktrees are restored as a whole, not file by file.
|
|
139
|
+
|
|
140
|
+
A worktree still open is reset to the point's patch (which also undoes
|
|
141
|
+
what shell commands changed, which no file checkpoint records); one that
|
|
142
|
+
is gone has nowhere to be restored to and is reopened from the patch.
|
|
143
|
+
The user's own files still go back by checkpoint.
|
|
144
|
+
"""
|
|
145
|
+
try:
|
|
146
|
+
from apps.cli import task_isolation
|
|
147
|
+
root = task_isolation.manager().root.resolve()
|
|
148
|
+
except Exception:
|
|
149
|
+
return lambda _path: False
|
|
150
|
+
|
|
151
|
+
def skip(path: str) -> bool:
|
|
152
|
+
try:
|
|
153
|
+
Path(path).resolve().relative_to(root)
|
|
154
|
+
return True
|
|
155
|
+
except (ValueError, OSError):
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
return skip
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _settle_open_task(terminal: Any, point: TransactionPoint) -> str:
|
|
162
|
+
"""The task open now, put back to what it was at ``point``."""
|
|
163
|
+
try:
|
|
164
|
+
from apps.cli import task_isolation
|
|
165
|
+
|
|
166
|
+
tasks = task_isolation.manager()
|
|
167
|
+
current = tasks.active(task_isolation._workspace(terminal.config))
|
|
168
|
+
except Exception as exc:
|
|
169
|
+
logger.debug("task state not restored: %s", exc)
|
|
170
|
+
return ""
|
|
171
|
+
if current is None:
|
|
172
|
+
return ""
|
|
173
|
+
saved = point.task or {}
|
|
174
|
+
if saved.get("path") == current.path:
|
|
175
|
+
tasks.reset_to_patch(current, str(saved.get("patch") or ""))
|
|
176
|
+
return "worktree reset to this point" if str(saved.get("patch") or "").strip() else ""
|
|
177
|
+
if current.created_at > point.created_at:
|
|
178
|
+
tasks.discard(current)
|
|
179
|
+
return f"discarded {current.task_id}, started after this point"
|
|
180
|
+
return ""
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _restore_task(terminal: Any, point: TransactionPoint) -> str:
|
|
184
|
+
saved = point.task
|
|
185
|
+
if not saved or not str(saved.get("patch") or "").strip():
|
|
186
|
+
return ""
|
|
187
|
+
if Path(saved["path"]).is_dir():
|
|
188
|
+
return "" # still open: its files were restored with the rest
|
|
189
|
+
from apps.cli import task_isolation
|
|
190
|
+
|
|
191
|
+
tasks = task_isolation.manager()
|
|
192
|
+
try:
|
|
193
|
+
task = tasks.ensure(task_isolation._workspace(terminal.config))
|
|
194
|
+
if task is None:
|
|
195
|
+
raise RuntimeError("not a git repository")
|
|
196
|
+
tasks.restore_patch(task, saved["patch"])
|
|
197
|
+
return f"reopened as {task.task_id} with its unapplied changes"
|
|
198
|
+
except Exception as exc:
|
|
199
|
+
keep = Path(tasks.root) / f"rewound-{saved['task_id']}.patch"
|
|
200
|
+
keep.parent.mkdir(parents=True, exist_ok=True)
|
|
201
|
+
keep.write_text(saved["patch"], encoding="utf-8")
|
|
202
|
+
return f"could not be reopened ({exc}); its changes are saved in {keep}"
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _cancel_later_tasks(terminal: Any, point: TransactionPoint) -> list[str]:
|
|
206
|
+
try:
|
|
207
|
+
from runtime.subagent import _TASKS, tool_task_cancel
|
|
208
|
+
except Exception:
|
|
209
|
+
return []
|
|
210
|
+
session_id = str(getattr(terminal, "session_id", "") or "")
|
|
211
|
+
cancelled = []
|
|
212
|
+
for task in list(_TASKS.values()):
|
|
213
|
+
if task.created_at <= point.created_at or task.status not in ("pending", "running"):
|
|
214
|
+
continue
|
|
215
|
+
if task.session_id and session_id and task.session_id != session_id:
|
|
216
|
+
continue
|
|
217
|
+
if tool_task_cancel({"task_id": task.task_id}).get("success"):
|
|
218
|
+
cancelled.append(task.task_id)
|
|
219
|
+
return cancelled
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def rewind(terminal: Any, point: TransactionPoint) -> RewindOutcome:
|
|
223
|
+
"""Put the session back to ``point``. Raises if files cannot be restored."""
|
|
224
|
+
session_id = str(getattr(terminal, "session_id", "") or "default")
|
|
225
|
+
files = _checkpoints().restore_since(point.checkpoint_sequence, session_id=session_id,
|
|
226
|
+
skip=_worktree_skip(terminal))
|
|
227
|
+
outcome = RewindOutcome(point=point, restored_paths=files.restored_paths)
|
|
228
|
+
notes = [_settle_open_task(terminal, point), _restore_task(terminal, point)]
|
|
229
|
+
outcome.task_note = "; ".join(note for note in notes if note)
|
|
230
|
+
|
|
231
|
+
outcome.messages_removed = max(0, len(terminal.conversation) - len(point.messages))
|
|
232
|
+
terminal.conversation[:] = list(point.messages)
|
|
233
|
+
|
|
234
|
+
todos = _todos()
|
|
235
|
+
todos._ACTIVE_TODOS[:] = list(point.todos)
|
|
236
|
+
|
|
237
|
+
namespace = _namespace(terminal)
|
|
238
|
+
before = _approvals(namespace)
|
|
239
|
+
saved = point.approvals or {}
|
|
240
|
+
namespace["_auto_approve_session"] = bool(saved.get("allow_all", False))
|
|
241
|
+
for key, values in (("_session_always_allow", saved.get("tools") or ()),
|
|
242
|
+
("_session_command_prefixes", [tuple(p) for p in saved.get("prefixes") or ()])):
|
|
243
|
+
current = namespace.get(key)
|
|
244
|
+
if isinstance(current, set):
|
|
245
|
+
current.clear()
|
|
246
|
+
current.update(values)
|
|
247
|
+
revoked = [tool for tool in before["tools"] if tool not in (saved.get("tools") or ())]
|
|
248
|
+
revoked += [" ".join(prefix) for prefix in before["prefixes"] if prefix not in (saved.get("prefixes") or [])]
|
|
249
|
+
if before["allow_all"] and not saved.get("allow_all"):
|
|
250
|
+
revoked.insert(0, "allow-all")
|
|
251
|
+
outcome.approvals_revoked = revoked
|
|
252
|
+
|
|
253
|
+
outcome.tasks_cancelled = _cancel_later_tasks(terminal, point)
|
|
254
|
+
terminal._code_verdict = point.verdict
|
|
255
|
+
store().drop_from(point)
|
|
256
|
+
return outcome
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def describe(points: list[TransactionPoint], *, now: Optional[float] = None) -> list[str]:
|
|
260
|
+
"""``/rewind turns``: newest first, numbered as ``/rewind turn N`` takes them."""
|
|
261
|
+
now = now or time.time()
|
|
262
|
+
marks = {"passed": "✓", "failed": "✗", "preexisting": "≈", "unverified": "·", "": " "}
|
|
263
|
+
lines = []
|
|
264
|
+
for index, point in enumerate(points, 1):
|
|
265
|
+
age = now - point.created_at
|
|
266
|
+
when = f"{int(age)}s" if age < 60 else f"{int(age // 60)}m" if age < 3600 else f"{age / 3600:.1f}h"
|
|
267
|
+
lines.append(f" {index:>2} {point.point_id[:8]} {marks.get(point.verdict, ' ')} "
|
|
268
|
+
f"{when:>5} ago before turn {point.turn}: {point.prompt[:60]}")
|
|
269
|
+
return lines
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Per-turn planning DECISIONS for send_message (pure, testable).
|
|
2
|
+
|
|
3
|
+
Extracted from ``aria_cli.send_message`` — the first slice of the file's
|
|
4
|
+
1300+ line stateful method to be pulled out. This module holds only the
|
|
5
|
+
*decision* logic (round budget, whether to trigger AI decomposition), which
|
|
6
|
+
depends solely on the user's message text and has no I/O, no ``self`` state,
|
|
7
|
+
and no side effects. It is safe to unit-test in isolation and safe to extract
|
|
8
|
+
without any behavior change, unlike the surrounding streaming/tool-loop code.
|
|
9
|
+
|
|
10
|
+
Mirrors send_message's inline logic exactly:
|
|
11
|
+
• task complexity → message > 120 chars, or contains a multi-step keyword
|
|
12
|
+
• round budget → complex tasks get a larger soft/hard round budget
|
|
13
|
+
• decomposition → long (>150 char), complex, non-slash-command messages
|
|
14
|
+
trigger an upfront AI decomposition pass
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
TASK_COMPLEXITY_LENGTH_THRESHOLD = 120
|
|
20
|
+
|
|
21
|
+
TASK_COMPLEXITY_KEYWORDS = (
|
|
22
|
+
"然后", "接着", "最后", "步骤", "并且", "同时",
|
|
23
|
+
"and then", "step", "finally", "after that", "next",
|
|
24
|
+
"完整", "全面", "详细", "系统", "comprehensive", "complete",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
DECOMP_THRESHOLD = 150 # chars
|
|
28
|
+
|
|
29
|
+
SOFT_ROUND_BUDGET_SIMPLE = 16
|
|
30
|
+
SOFT_ROUND_BUDGET_COMPLEX = 30
|
|
31
|
+
HARD_ROUND_EXTENSION_SIMPLE = 10
|
|
32
|
+
HARD_ROUND_EXTENSION_COMPLEX = 20
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def is_complex_task(message: str) -> bool:
|
|
36
|
+
"""A message is 'complex' if it's long or names a multi-step structure."""
|
|
37
|
+
return (
|
|
38
|
+
len(message) > TASK_COMPLEXITY_LENGTH_THRESHOLD
|
|
39
|
+
or any(kw in message for kw in TASK_COMPLEXITY_KEYWORDS)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def round_budget_for(is_complex: bool) -> tuple[int, int]:
|
|
44
|
+
"""-> (max_rounds, hard_max_rounds). Complex tasks get a larger budget
|
|
45
|
+
on both the soft limit (where we start checking for real progress) and
|
|
46
|
+
the hard extension (how far a still-progressing task can run past it)."""
|
|
47
|
+
max_rounds = SOFT_ROUND_BUDGET_COMPLEX if is_complex else SOFT_ROUND_BUDGET_SIMPLE
|
|
48
|
+
hard_max_rounds = max_rounds + (
|
|
49
|
+
HARD_ROUND_EXTENSION_COMPLEX if is_complex else HARD_ROUND_EXTENSION_SIMPLE
|
|
50
|
+
)
|
|
51
|
+
return max_rounds, hard_max_rounds
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def should_decompose(message: str, is_complex: bool) -> bool:
|
|
55
|
+
"""Trigger an upfront AI decomposition pass for long, complex, non-slash
|
|
56
|
+
messages. Slash commands (``/...``) and bang commands (``!...``) are never
|
|
57
|
+
decomposed — they're already a single deterministic action."""
|
|
58
|
+
return (
|
|
59
|
+
len(message) > DECOMP_THRESHOLD
|
|
60
|
+
and is_complex
|
|
61
|
+
and not any(message.startswith(p) for p in ("/", "!"))
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ── post-turn context pressure ───────────────────────────────────────────────
|
|
66
|
+
# send_message had three separate places that decide whether history is too hot
|
|
67
|
+
# to carry into the next turn, and they disagreed. The usage-driven one (real
|
|
68
|
+
# provider prompt_tokens) and the pre-turn one both honour auto_compact_context
|
|
69
|
+
# and auto_compact_threshold; the post-turn char-estimate one honoured neither
|
|
70
|
+
# and hardcoded 90% compact / 70% warn. So `/config set
|
|
71
|
+
# auto_compact_context=false` did not turn auto-compaction off — /status said
|
|
72
|
+
# "auto compact off" while the third path still compacted — and a threshold of
|
|
73
|
+
# 0.95 was capped at the hidden 0.90.
|
|
74
|
+
#
|
|
75
|
+
# Warning is deliberately NOT gated on the toggle. Turning auto-compaction off
|
|
76
|
+
# means "do not rewrite my history", not "stop telling me how full it is" —
|
|
77
|
+
# and it is precisely the user who disabled compaction who needs to be told to
|
|
78
|
+
# run /compact.
|
|
79
|
+
|
|
80
|
+
CONTEXT_WARN_FRACTION = 0.70
|
|
81
|
+
CHARS_PER_TOKEN_ESTIMATE = 3
|
|
82
|
+
DEFAULT_COMPACT_THRESHOLD = 0.78
|
|
83
|
+
MIN_COMPACT_THRESHOLD = 0.50
|
|
84
|
+
MAX_COMPACT_THRESHOLD = 0.95
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def estimate_context_tokens(conversation: list) -> int:
|
|
88
|
+
"""Rough token count for a conversation, by characters."""
|
|
89
|
+
return sum(
|
|
90
|
+
len(m.get("content", "") or "") for m in (conversation or [])
|
|
91
|
+
) // CHARS_PER_TOKEN_ESTIMATE
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def clamp_compact_threshold(value) -> float:
|
|
95
|
+
"""Config threshold as a fraction, clamped to the range /config accepts."""
|
|
96
|
+
try:
|
|
97
|
+
threshold = float(value)
|
|
98
|
+
except (TypeError, ValueError):
|
|
99
|
+
return DEFAULT_COMPACT_THRESHOLD
|
|
100
|
+
return max(MIN_COMPACT_THRESHOLD, min(MAX_COMPACT_THRESHOLD, threshold))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def post_turn_context_decision(
|
|
104
|
+
used_tokens: int,
|
|
105
|
+
max_tokens: int,
|
|
106
|
+
*,
|
|
107
|
+
auto_compact_enabled: bool = True,
|
|
108
|
+
threshold=DEFAULT_COMPACT_THRESHOLD,
|
|
109
|
+
already_compacted: bool = False,
|
|
110
|
+
) -> dict:
|
|
111
|
+
"""-> {"fill_pct", "should_compact", "should_warn"}.
|
|
112
|
+
|
|
113
|
+
``already_compacted`` is the usage-driven path having fired this turn; it
|
|
114
|
+
suppresses both outcomes so one turn never compacts twice or warns about a
|
|
115
|
+
figure it just fixed.
|
|
116
|
+
"""
|
|
117
|
+
if max_tokens <= 0:
|
|
118
|
+
return {"fill_pct": 0, "should_compact": False, "should_warn": False}
|
|
119
|
+
|
|
120
|
+
fill_pct = min(100, int(used_tokens / max_tokens * 100))
|
|
121
|
+
limit_pct = clamp_compact_threshold(threshold) * 100
|
|
122
|
+
|
|
123
|
+
should_compact = (
|
|
124
|
+
bool(auto_compact_enabled)
|
|
125
|
+
and not already_compacted
|
|
126
|
+
and fill_pct >= limit_pct
|
|
127
|
+
)
|
|
128
|
+
should_warn = (
|
|
129
|
+
not should_compact
|
|
130
|
+
and not already_compacted
|
|
131
|
+
and fill_pct >= CONTEXT_WARN_FRACTION * 100
|
|
132
|
+
)
|
|
133
|
+
return {
|
|
134
|
+
"fill_pct": fill_pct,
|
|
135
|
+
"should_compact": should_compact,
|
|
136
|
+
"should_warn": should_warn,
|
|
137
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"""Background version checker for the active Aria Code install channel.
|
|
2
|
+
|
|
3
|
+
Checks GitHub releases or scoped npm once per 24 hours in a daemon thread so
|
|
4
|
+
startup is never blocked. The result is cached in the Aria home directory and read
|
|
5
|
+
at banner render time.
|
|
6
|
+
|
|
7
|
+
Public API
|
|
8
|
+
----------
|
|
9
|
+
start_update_check(current_version: str) -> None
|
|
10
|
+
Call once, early in startup. Spawns daemon thread; returns immediately.
|
|
11
|
+
|
|
12
|
+
get_update_notice() -> str | None
|
|
13
|
+
Call at banner render time. Returns a Rich-markup string if a newer
|
|
14
|
+
version is available, otherwise None. Thread-safe — safe to call
|
|
15
|
+
before the background thread finishes (returns cached result then).
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import subprocess
|
|
22
|
+
import sys
|
|
23
|
+
import threading
|
|
24
|
+
import time
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from typing import Optional
|
|
27
|
+
from aria_code.packages.aria_core.paths import aria_home
|
|
28
|
+
|
|
29
|
+
_RELEASE_URL = "https://api.github.com/repos/artheras/aria-code/releases/latest"
|
|
30
|
+
_NPM_URL = "https://registry.npmjs.org/@artheras%2Faria-code/latest"
|
|
31
|
+
_CACHE_FILE = aria_home() / "update_check.json"
|
|
32
|
+
_CACHE_TTL_S = 86_400 # 24 hours
|
|
33
|
+
_FETCH_TIMEOUT = 4 # seconds — fail cleanly on slow networks
|
|
34
|
+
|
|
35
|
+
# These are the project's historical PyPI releases (June–August 2026),
|
|
36
|
+
# published before the current 0.x line. Do not treat arbitrary future 4.x
|
|
37
|
+
# versions as legacy, or recommend these old artifacts to a current install.
|
|
38
|
+
_LEGACY_VERSIONS = frozenset({
|
|
39
|
+
(4, 1, 3), (4, 1, 4), (4, 1, 7), (4, 2, 0),
|
|
40
|
+
(4, 3, 0), (4, 4, 0), (4, 4, 1), (4, 4, 2),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
_notice: Optional[str] = None
|
|
44
|
+
_lock = threading.Lock()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ── Version comparison ────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
def _parse(v: str) -> tuple[int, int, int] | None:
|
|
50
|
+
"""Accept only stable project release tags, never another package's version."""
|
|
51
|
+
import re
|
|
52
|
+
match = re.fullmatch(r"v?(\d+)\.(\d+)\.(\d+)", v.strip())
|
|
53
|
+
return tuple(map(int, match.groups())) if match else None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _newer(latest: str, current: str) -> bool:
|
|
57
|
+
parsed_latest, parsed_current = _parse(latest), _parse(current)
|
|
58
|
+
if parsed_latest is None or parsed_current is None:
|
|
59
|
+
return False
|
|
60
|
+
if parsed_current in _LEGACY_VERSIONS and parsed_latest[0] == 0:
|
|
61
|
+
return True
|
|
62
|
+
if parsed_latest in _LEGACY_VERSIONS and parsed_current[0] == 0:
|
|
63
|
+
return False
|
|
64
|
+
return parsed_latest > parsed_current
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ── Cache helpers ─────────────────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
def _read_cache() -> dict:
|
|
70
|
+
try:
|
|
71
|
+
return json.loads(_CACHE_FILE.read_text())
|
|
72
|
+
except Exception:
|
|
73
|
+
return {}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _write_cache(data: dict) -> None:
|
|
77
|
+
try:
|
|
78
|
+
_CACHE_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
79
|
+
_CACHE_FILE.write_text(json.dumps(data))
|
|
80
|
+
except Exception:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# ── Notice builder ────────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
def _install_channel() -> str:
|
|
87
|
+
"""Infer which update channel owns the running executable."""
|
|
88
|
+
override = os.environ.get("ARIA_CODE_INSTALL_CHANNEL", "").lower()
|
|
89
|
+
if override in ("npm", "native", "pip", "source"):
|
|
90
|
+
return override
|
|
91
|
+
executable = str(getattr(sys, "executable", "") or "").lower()
|
|
92
|
+
if "node_modules" in executable and "aria" in executable:
|
|
93
|
+
return "npm"
|
|
94
|
+
if getattr(sys, "frozen", False):
|
|
95
|
+
return "native"
|
|
96
|
+
root = Path(__file__).resolve().parents[4]
|
|
97
|
+
if (root / ".git").exists() and (root / "pyproject.toml").exists():
|
|
98
|
+
return "source"
|
|
99
|
+
return "pip"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _update_command(channel: str, latest: str = "") -> str:
|
|
103
|
+
if channel == "npm":
|
|
104
|
+
return "npm install -g @artheras/aria-code@latest"
|
|
105
|
+
if channel == "source":
|
|
106
|
+
return "git pull && python3 -m pip install -e ."
|
|
107
|
+
if channel == "pip":
|
|
108
|
+
# Pinned: PyPI still lists an older 4.x numbering, so an unpinned
|
|
109
|
+
# --upgrade "updates" 0.73.0 to 4.4.2, which is older code.
|
|
110
|
+
return f'python3 -m pip install --upgrade "aria-code=={latest}"' if latest else \
|
|
111
|
+
'python3 -m pip install --upgrade "aria-code<4"'
|
|
112
|
+
if sys.platform == "win32":
|
|
113
|
+
return "irm https://raw.githubusercontent.com/artheras/aria-code/main/scripts/install.ps1 | iex"
|
|
114
|
+
return "curl -fsSL https://raw.githubusercontent.com/artheras/aria-code/main/scripts/install.sh | sh"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _build_notice(latest: str, current: str, lang: str, channel: str = "native") -> str:
|
|
118
|
+
latest = latest.removeprefix("v")
|
|
119
|
+
current = current.removeprefix("v")
|
|
120
|
+
cmd = _update_command(channel, latest) if channel == "source" or (channel == "native" and sys.platform == "win32") else "aria update"
|
|
121
|
+
if lang == "zh":
|
|
122
|
+
return (
|
|
123
|
+
f"[yellow]⬆ 新版本可用[/yellow] "
|
|
124
|
+
f"[dim]v{current}[/dim] [dim]→[/dim] [bold]v{latest}[/bold]"
|
|
125
|
+
f" [dim]{cmd}[/dim]"
|
|
126
|
+
)
|
|
127
|
+
return (
|
|
128
|
+
f"[yellow]⬆ Update available[/yellow] "
|
|
129
|
+
f"[dim]v{current}[/dim] [dim]→[/dim] [bold]v{latest}[/bold]"
|
|
130
|
+
f" [dim]{cmd}[/dim]"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ── Background worker ─────────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
def _worker(current: str, lang: str, channel: str = "native") -> None:
|
|
137
|
+
global _notice
|
|
138
|
+
# GitHub releases are the version of record for every channel but npm.
|
|
139
|
+
# PyPI's own "latest" is not: it still points at the old 4.x line.
|
|
140
|
+
source_url, version_field = (_NPM_URL, "version") if channel == "npm" else (_RELEASE_URL, "tag_name")
|
|
141
|
+
|
|
142
|
+
# 1. Serve from cache if still fresh
|
|
143
|
+
cache = _read_cache()
|
|
144
|
+
now = time.time()
|
|
145
|
+
if cache.get("source") == source_url and cache.get("checked_at", 0) + _CACHE_TTL_S > now:
|
|
146
|
+
latest = cache.get("latest", "")
|
|
147
|
+
if latest and _newer(latest, current):
|
|
148
|
+
with _lock:
|
|
149
|
+
_notice = _build_notice(latest, current, lang, channel)
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
# 2. Fetch metadata for this installation channel, never a similarly named package.
|
|
153
|
+
latest = _native_latest(current, channel)
|
|
154
|
+
if latest is None:
|
|
155
|
+
try:
|
|
156
|
+
import urllib.request
|
|
157
|
+
req = urllib.request.Request(
|
|
158
|
+
source_url,
|
|
159
|
+
headers={"Accept": "application/json", "User-Agent": "aria-code-update-check"},
|
|
160
|
+
)
|
|
161
|
+
with urllib.request.urlopen(req, timeout=_FETCH_TIMEOUT) as resp:
|
|
162
|
+
data = json.loads(resp.read())
|
|
163
|
+
latest = data[version_field]
|
|
164
|
+
except Exception:
|
|
165
|
+
return # background checks never interrupt the user's work
|
|
166
|
+
|
|
167
|
+
# 3. Persist to cache
|
|
168
|
+
if _parse(latest) is None:
|
|
169
|
+
return
|
|
170
|
+
_write_cache({"source": source_url, "checked_at": now, "latest": latest})
|
|
171
|
+
|
|
172
|
+
# 4. Set notice
|
|
173
|
+
if _newer(latest, current):
|
|
174
|
+
with _lock:
|
|
175
|
+
_notice = _build_notice(latest, current, lang, channel)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _native_latest(current: str, channel: str) -> str | None:
|
|
179
|
+
"""Ask the bundled Rust updater to validate/cache release metadata.
|
|
180
|
+
|
|
181
|
+
Return None when the helper is unavailable or incompatible so older
|
|
182
|
+
packages and Windows keep their established Python check path.
|
|
183
|
+
"""
|
|
184
|
+
payload = _native_check(current, channel)
|
|
185
|
+
latest = payload.get("latest") if payload else None
|
|
186
|
+
return latest.removeprefix("v") if isinstance(latest, str) and _parse(latest) else None
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _native_check(current: str, channel: str, *, refresh: bool = False) -> dict | None:
|
|
190
|
+
"""Return checked metadata from the bundled Rust updater, if available."""
|
|
191
|
+
try:
|
|
192
|
+
# Lazy import avoids a module cycle: updater imports this module's
|
|
193
|
+
# release constants and version helpers.
|
|
194
|
+
from aria_code.apps.cli.updater import _native_update_helper
|
|
195
|
+
|
|
196
|
+
helper = _native_update_helper()
|
|
197
|
+
if helper is None:
|
|
198
|
+
return None
|
|
199
|
+
command = [str(helper), "update", "check", "--current", current, "--channel", channel]
|
|
200
|
+
if refresh:
|
|
201
|
+
command.append("--refresh")
|
|
202
|
+
result = subprocess.run(
|
|
203
|
+
command,
|
|
204
|
+
capture_output=True,
|
|
205
|
+
text=True,
|
|
206
|
+
timeout=_FETCH_TIMEOUT + 2,
|
|
207
|
+
check=False,
|
|
208
|
+
)
|
|
209
|
+
if result.returncode != 0:
|
|
210
|
+
return None
|
|
211
|
+
payload = json.loads(result.stdout)
|
|
212
|
+
return payload if isinstance(payload, dict) else None
|
|
213
|
+
except Exception:
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# ── Public API ────────────────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
def start_update_check(current_version: str, lang: str = "en", enabled: bool = True) -> None:
|
|
220
|
+
"""Start background version check. Call once, early in startup."""
|
|
221
|
+
global _notice
|
|
222
|
+
with _lock:
|
|
223
|
+
_notice = None
|
|
224
|
+
if not enabled:
|
|
225
|
+
return
|
|
226
|
+
channel = _install_channel()
|
|
227
|
+
source = _NPM_URL if channel == "npm" else _RELEASE_URL
|
|
228
|
+
cache = _read_cache()
|
|
229
|
+
if cache.get("source") == source and _newer(cache.get("latest", ""), current_version):
|
|
230
|
+
with _lock:
|
|
231
|
+
_notice = _build_notice(cache["latest"], current_version, lang, channel)
|
|
232
|
+
t = threading.Thread(
|
|
233
|
+
target=_worker,
|
|
234
|
+
args=(current_version, lang, channel),
|
|
235
|
+
daemon=True,
|
|
236
|
+
name="aria-update-check",
|
|
237
|
+
)
|
|
238
|
+
t.start()
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_update_notice(wait_ms: int = 0) -> Optional[str]:
|
|
242
|
+
"""Return Rich-markup update notice, or None if up to date / not yet known.
|
|
243
|
+
|
|
244
|
+
Read the cached notice immediately. An explicit wait is supported for
|
|
245
|
+
callers outside startup, but startup never waits for a network request.
|
|
246
|
+
"""
|
|
247
|
+
deadline = time.monotonic() + wait_ms / 1000
|
|
248
|
+
while time.monotonic() < deadline:
|
|
249
|
+
with _lock:
|
|
250
|
+
if _notice is not None:
|
|
251
|
+
return _notice
|
|
252
|
+
alive = any(t.name == "aria-update-check" for t in threading.enumerate())
|
|
253
|
+
if not alive:
|
|
254
|
+
break
|
|
255
|
+
time.sleep(0.05)
|
|
256
|
+
with _lock:
|
|
257
|
+
return _notice
|