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,481 @@
|
|
|
1
|
+
"""Durable, conflict-aware file checkpoints for agent write operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import sqlite3
|
|
9
|
+
import stat
|
|
10
|
+
import time
|
|
11
|
+
import uuid
|
|
12
|
+
from dataclasses import dataclass, field, replace
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any, Callable, Dict, Iterable, Optional
|
|
15
|
+
|
|
16
|
+
from .run_store import RunStore
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _sha256(content: str) -> str:
|
|
20
|
+
return hashlib.sha256(content.encode("utf-8", errors="replace")).hexdigest()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _json_dumps(value: Any) -> str:
|
|
24
|
+
return json.dumps(value, ensure_ascii=False, default=str, separators=(",", ":"))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _json_loads(value: str | None) -> Dict[str, Any]:
|
|
28
|
+
if not value:
|
|
29
|
+
return {}
|
|
30
|
+
try:
|
|
31
|
+
loaded = json.loads(value)
|
|
32
|
+
return loaded if isinstance(loaded, dict) else {"value": loaded}
|
|
33
|
+
except (TypeError, json.JSONDecodeError):
|
|
34
|
+
return {}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class CheckpointFile:
|
|
39
|
+
checkpoint_id: str
|
|
40
|
+
path: str
|
|
41
|
+
existed_before: bool
|
|
42
|
+
before_content: str
|
|
43
|
+
after_content: str
|
|
44
|
+
before_hash: str
|
|
45
|
+
after_hash: str
|
|
46
|
+
before_mode: Optional[int]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class CheckpointRecord:
|
|
51
|
+
checkpoint_id: str
|
|
52
|
+
sequence: int
|
|
53
|
+
run_id: Optional[str]
|
|
54
|
+
session_id: str
|
|
55
|
+
source: str
|
|
56
|
+
label: str
|
|
57
|
+
status: str
|
|
58
|
+
created_at: float
|
|
59
|
+
restored_at: Optional[float]
|
|
60
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
61
|
+
files: tuple[CheckpointFile, ...] = ()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True)
|
|
65
|
+
class RestoreResult:
|
|
66
|
+
checkpoint_ids: tuple[str, ...]
|
|
67
|
+
run_id: Optional[str]
|
|
68
|
+
restored_paths: tuple[str, ...]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class CheckpointNotFoundError(KeyError):
|
|
72
|
+
"""Raised when a checkpoint or checkpoint group cannot be found."""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class CheckpointConflictError(RuntimeError):
|
|
76
|
+
"""Raised when a file changed after the checkpoint was recorded."""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class CheckpointStore:
|
|
80
|
+
"""Store file pre-images and restore them only when hashes still match."""
|
|
81
|
+
|
|
82
|
+
def __init__(self, database_path: Path | str | None = None) -> None:
|
|
83
|
+
self.run_store = RunStore(database_path)
|
|
84
|
+
self.database_path = self.run_store.database_path
|
|
85
|
+
self._initialize()
|
|
86
|
+
|
|
87
|
+
def _connect(self) -> sqlite3.Connection:
|
|
88
|
+
connection = sqlite3.connect(str(self.database_path), timeout=10.0)
|
|
89
|
+
connection.row_factory = sqlite3.Row
|
|
90
|
+
connection.execute("PRAGMA foreign_keys = ON")
|
|
91
|
+
connection.execute("PRAGMA busy_timeout = 10000")
|
|
92
|
+
return connection
|
|
93
|
+
|
|
94
|
+
def _initialize(self) -> None:
|
|
95
|
+
with self._connect() as connection:
|
|
96
|
+
connection.executescript(
|
|
97
|
+
"""
|
|
98
|
+
CREATE TABLE IF NOT EXISTS checkpoints (
|
|
99
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
100
|
+
checkpoint_id TEXT NOT NULL UNIQUE,
|
|
101
|
+
run_id TEXT,
|
|
102
|
+
session_id TEXT NOT NULL DEFAULT '',
|
|
103
|
+
source TEXT NOT NULL,
|
|
104
|
+
label TEXT NOT NULL DEFAULT '',
|
|
105
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
106
|
+
created_at REAL NOT NULL,
|
|
107
|
+
restored_at REAL,
|
|
108
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
109
|
+
FOREIGN KEY(run_id) REFERENCES runs(run_id)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
CREATE TABLE IF NOT EXISTS checkpoint_files (
|
|
113
|
+
checkpoint_id TEXT NOT NULL,
|
|
114
|
+
path TEXT NOT NULL,
|
|
115
|
+
existed_before INTEGER NOT NULL,
|
|
116
|
+
before_content TEXT NOT NULL,
|
|
117
|
+
after_content TEXT NOT NULL,
|
|
118
|
+
before_hash TEXT NOT NULL,
|
|
119
|
+
after_hash TEXT NOT NULL,
|
|
120
|
+
before_mode INTEGER,
|
|
121
|
+
PRIMARY KEY(checkpoint_id, path),
|
|
122
|
+
FOREIGN KEY(checkpoint_id)
|
|
123
|
+
REFERENCES checkpoints(checkpoint_id) ON DELETE CASCADE
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
CREATE INDEX IF NOT EXISTS idx_checkpoints_run_sequence
|
|
127
|
+
ON checkpoints(run_id, sequence DESC);
|
|
128
|
+
CREATE INDEX IF NOT EXISTS idx_checkpoints_session_sequence
|
|
129
|
+
ON checkpoints(session_id, sequence DESC);
|
|
130
|
+
CREATE INDEX IF NOT EXISTS idx_checkpoints_status_sequence
|
|
131
|
+
ON checkpoints(status, sequence DESC);
|
|
132
|
+
"""
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def _row_to_file(row: sqlite3.Row) -> CheckpointFile:
|
|
137
|
+
return CheckpointFile(
|
|
138
|
+
checkpoint_id=row["checkpoint_id"],
|
|
139
|
+
path=row["path"],
|
|
140
|
+
existed_before=bool(row["existed_before"]),
|
|
141
|
+
before_content=row["before_content"],
|
|
142
|
+
after_content=row["after_content"],
|
|
143
|
+
before_hash=row["before_hash"],
|
|
144
|
+
after_hash=row["after_hash"],
|
|
145
|
+
before_mode=int(row["before_mode"]) if row["before_mode"] is not None else None,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
def _row_to_checkpoint(
|
|
149
|
+
self,
|
|
150
|
+
connection: sqlite3.Connection,
|
|
151
|
+
row: sqlite3.Row,
|
|
152
|
+
) -> CheckpointRecord:
|
|
153
|
+
file_rows = connection.execute(
|
|
154
|
+
"SELECT * FROM checkpoint_files WHERE checkpoint_id = ? ORDER BY path",
|
|
155
|
+
(row["checkpoint_id"],),
|
|
156
|
+
).fetchall()
|
|
157
|
+
return CheckpointRecord(
|
|
158
|
+
checkpoint_id=row["checkpoint_id"],
|
|
159
|
+
sequence=int(row["sequence"]),
|
|
160
|
+
run_id=row["run_id"],
|
|
161
|
+
session_id=row["session_id"],
|
|
162
|
+
source=row["source"],
|
|
163
|
+
label=row["label"],
|
|
164
|
+
status=row["status"],
|
|
165
|
+
created_at=float(row["created_at"]),
|
|
166
|
+
restored_at=float(row["restored_at"]) if row["restored_at"] is not None else None,
|
|
167
|
+
metadata=_json_loads(row["metadata_json"]),
|
|
168
|
+
files=tuple(self._row_to_file(file_row) for file_row in file_rows),
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def record_change(
|
|
172
|
+
self,
|
|
173
|
+
*,
|
|
174
|
+
path: Path | str,
|
|
175
|
+
before_content: str,
|
|
176
|
+
after_content: str,
|
|
177
|
+
existed_before: bool,
|
|
178
|
+
source: str,
|
|
179
|
+
run_id: str | None = None,
|
|
180
|
+
session_id: str = "",
|
|
181
|
+
before_mode: int | None = None,
|
|
182
|
+
label: str = "",
|
|
183
|
+
metadata: Dict[str, Any] | None = None,
|
|
184
|
+
) -> CheckpointRecord:
|
|
185
|
+
target = Path(path).expanduser().resolve()
|
|
186
|
+
if not target.is_file():
|
|
187
|
+
raise CheckpointConflictError(f"Written file is missing: {target}")
|
|
188
|
+
current = target.read_text(encoding="utf-8", errors="replace")
|
|
189
|
+
after_hash = _sha256(after_content)
|
|
190
|
+
if _sha256(current) != after_hash:
|
|
191
|
+
raise CheckpointConflictError(
|
|
192
|
+
f"File changed before checkpoint could be recorded: {target}"
|
|
193
|
+
)
|
|
194
|
+
if run_id and self.run_store.get_run(run_id) is None:
|
|
195
|
+
raise CheckpointNotFoundError(f"Unknown run id: {run_id}")
|
|
196
|
+
|
|
197
|
+
checkpoint_id = uuid.uuid4().hex[:16]
|
|
198
|
+
created_at = time.time()
|
|
199
|
+
mode = before_mode
|
|
200
|
+
if existed_before and mode is None:
|
|
201
|
+
mode = stat.S_IMODE(target.stat().st_mode)
|
|
202
|
+
with self._connect() as connection:
|
|
203
|
+
connection.execute("BEGIN IMMEDIATE")
|
|
204
|
+
connection.execute(
|
|
205
|
+
"""INSERT INTO checkpoints
|
|
206
|
+
(checkpoint_id, run_id, session_id, source, label, status,
|
|
207
|
+
created_at, restored_at, metadata_json)
|
|
208
|
+
VALUES (?, ?, ?, ?, ?, 'active', ?, NULL, ?)""",
|
|
209
|
+
(
|
|
210
|
+
checkpoint_id,
|
|
211
|
+
run_id,
|
|
212
|
+
session_id,
|
|
213
|
+
source,
|
|
214
|
+
label,
|
|
215
|
+
created_at,
|
|
216
|
+
_json_dumps(metadata or {}),
|
|
217
|
+
),
|
|
218
|
+
)
|
|
219
|
+
connection.execute(
|
|
220
|
+
"""INSERT INTO checkpoint_files
|
|
221
|
+
(checkpoint_id, path, existed_before, before_content,
|
|
222
|
+
after_content, before_hash, after_hash, before_mode)
|
|
223
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
|
224
|
+
(
|
|
225
|
+
checkpoint_id,
|
|
226
|
+
str(target),
|
|
227
|
+
int(existed_before),
|
|
228
|
+
before_content,
|
|
229
|
+
after_content,
|
|
230
|
+
_sha256(before_content),
|
|
231
|
+
after_hash,
|
|
232
|
+
mode,
|
|
233
|
+
),
|
|
234
|
+
)
|
|
235
|
+
row = connection.execute(
|
|
236
|
+
"SELECT * FROM checkpoints WHERE checkpoint_id = ?",
|
|
237
|
+
(checkpoint_id,),
|
|
238
|
+
).fetchone()
|
|
239
|
+
|
|
240
|
+
if run_id:
|
|
241
|
+
self.run_store.append_event(run_id, "checkpoint_created", {
|
|
242
|
+
"checkpoint_id": checkpoint_id,
|
|
243
|
+
"path": str(target),
|
|
244
|
+
"source": source,
|
|
245
|
+
})
|
|
246
|
+
assert row is not None
|
|
247
|
+
with self._connect() as connection:
|
|
248
|
+
return self._row_to_checkpoint(connection, row)
|
|
249
|
+
|
|
250
|
+
def get(self, checkpoint_id: str) -> Optional[CheckpointRecord]:
|
|
251
|
+
key = (checkpoint_id or "").strip()
|
|
252
|
+
with self._connect() as connection:
|
|
253
|
+
row = connection.execute(
|
|
254
|
+
"SELECT * FROM checkpoints WHERE checkpoint_id = ?",
|
|
255
|
+
(key,),
|
|
256
|
+
).fetchone()
|
|
257
|
+
if row is None and key:
|
|
258
|
+
rows = connection.execute(
|
|
259
|
+
"SELECT * FROM checkpoints WHERE checkpoint_id LIKE ? ORDER BY sequence DESC LIMIT 2",
|
|
260
|
+
(f"{key}%",),
|
|
261
|
+
).fetchall()
|
|
262
|
+
row = rows[0] if len(rows) == 1 else None
|
|
263
|
+
return self._row_to_checkpoint(connection, row) if row is not None else None
|
|
264
|
+
|
|
265
|
+
def list(
|
|
266
|
+
self,
|
|
267
|
+
*,
|
|
268
|
+
run_id: str | None = None,
|
|
269
|
+
session_id: str | None = None,
|
|
270
|
+
status: str | None = "active",
|
|
271
|
+
limit: int = 50,
|
|
272
|
+
) -> list[CheckpointRecord]:
|
|
273
|
+
clauses = []
|
|
274
|
+
values: list[Any] = []
|
|
275
|
+
if run_id:
|
|
276
|
+
clauses.append("run_id = ?")
|
|
277
|
+
values.append(run_id)
|
|
278
|
+
if session_id:
|
|
279
|
+
clauses.append("session_id = ?")
|
|
280
|
+
values.append(session_id)
|
|
281
|
+
if status:
|
|
282
|
+
clauses.append("status = ?")
|
|
283
|
+
values.append(status)
|
|
284
|
+
where = f" WHERE {' AND '.join(clauses)}" if clauses else ""
|
|
285
|
+
values.append(max(1, int(limit)))
|
|
286
|
+
with self._connect() as connection:
|
|
287
|
+
rows = connection.execute(
|
|
288
|
+
f"SELECT * FROM checkpoints{where} ORDER BY sequence DESC LIMIT ?",
|
|
289
|
+
values,
|
|
290
|
+
).fetchall()
|
|
291
|
+
return [self._row_to_checkpoint(connection, row) for row in rows]
|
|
292
|
+
|
|
293
|
+
def latest_run_id(self, *, session_id: str | None = None) -> Optional[str]:
|
|
294
|
+
clauses = ["status = 'active'", "run_id IS NOT NULL"]
|
|
295
|
+
values: list[Any] = []
|
|
296
|
+
if session_id:
|
|
297
|
+
clauses.append("session_id = ?")
|
|
298
|
+
values.append(session_id)
|
|
299
|
+
with self._connect() as connection:
|
|
300
|
+
row = connection.execute(
|
|
301
|
+
f"SELECT run_id FROM checkpoints WHERE {' AND '.join(clauses)} "
|
|
302
|
+
"ORDER BY sequence DESC LIMIT 1",
|
|
303
|
+
values,
|
|
304
|
+
).fetchone()
|
|
305
|
+
return row["run_id"] if row is not None else None
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def _snapshot(path: Path) -> tuple[bool, str, Optional[int]]:
|
|
309
|
+
if not path.exists():
|
|
310
|
+
return False, "", None
|
|
311
|
+
if not path.is_file():
|
|
312
|
+
raise CheckpointConflictError(f"Checkpoint path is not a file: {path}")
|
|
313
|
+
return (
|
|
314
|
+
True,
|
|
315
|
+
path.read_text(encoding="utf-8", errors="replace"),
|
|
316
|
+
stat.S_IMODE(path.stat().st_mode),
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
@staticmethod
|
|
320
|
+
def _write_atomic(path: Path, content: str, mode: int | None) -> None:
|
|
321
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
322
|
+
temporary = path.with_name(f".{path.name}.aria-rewind-{uuid.uuid4().hex[:8]}")
|
|
323
|
+
try:
|
|
324
|
+
temporary.write_text(content, encoding="utf-8")
|
|
325
|
+
if mode is not None:
|
|
326
|
+
temporary.chmod(mode)
|
|
327
|
+
os.replace(temporary, path)
|
|
328
|
+
finally:
|
|
329
|
+
if temporary.exists():
|
|
330
|
+
temporary.unlink()
|
|
331
|
+
|
|
332
|
+
def _restore(self, checkpoints: Iterable[CheckpointRecord]) -> RestoreResult:
|
|
333
|
+
records = list(checkpoints)
|
|
334
|
+
if not records:
|
|
335
|
+
raise CheckpointNotFoundError("No active checkpoints to restore")
|
|
336
|
+
files = [file for record in records for file in record.files]
|
|
337
|
+
if not files:
|
|
338
|
+
raise CheckpointNotFoundError("Checkpoint contains no files")
|
|
339
|
+
|
|
340
|
+
simulated: Dict[str, tuple[bool, str]] = {}
|
|
341
|
+
backups: Dict[str, tuple[bool, str, Optional[int]]] = {}
|
|
342
|
+
for file in files:
|
|
343
|
+
path = Path(file.path)
|
|
344
|
+
if file.path not in simulated:
|
|
345
|
+
exists, content, mode = self._snapshot(path)
|
|
346
|
+
backups[file.path] = (exists, content, mode)
|
|
347
|
+
simulated[file.path] = (exists, _sha256(content))
|
|
348
|
+
exists, current_hash = simulated[file.path]
|
|
349
|
+
if not exists or current_hash != file.after_hash:
|
|
350
|
+
raise CheckpointConflictError(
|
|
351
|
+
f"Refusing to overwrite a file changed after the checkpoint: {path}"
|
|
352
|
+
)
|
|
353
|
+
simulated[file.path] = (file.existed_before, file.before_hash)
|
|
354
|
+
|
|
355
|
+
restored_paths: list[str] = []
|
|
356
|
+
try:
|
|
357
|
+
for file in files:
|
|
358
|
+
path = Path(file.path)
|
|
359
|
+
exists, current, _ = self._snapshot(path)
|
|
360
|
+
if not exists or _sha256(current) != file.after_hash:
|
|
361
|
+
raise CheckpointConflictError(
|
|
362
|
+
f"File changed while rewind was running: {path}"
|
|
363
|
+
)
|
|
364
|
+
if file.existed_before:
|
|
365
|
+
self._write_atomic(path, file.before_content, file.before_mode)
|
|
366
|
+
else:
|
|
367
|
+
path.unlink()
|
|
368
|
+
if file.path not in restored_paths:
|
|
369
|
+
restored_paths.append(file.path)
|
|
370
|
+
except Exception:
|
|
371
|
+
for path_text, (existed, content, mode) in backups.items():
|
|
372
|
+
path = Path(path_text)
|
|
373
|
+
if existed:
|
|
374
|
+
self._write_atomic(path, content, mode)
|
|
375
|
+
elif path.exists() and path.is_file():
|
|
376
|
+
path.unlink()
|
|
377
|
+
raise
|
|
378
|
+
|
|
379
|
+
restored_at = time.time()
|
|
380
|
+
checkpoint_ids = tuple(record.checkpoint_id for record in records)
|
|
381
|
+
with self._connect() as connection:
|
|
382
|
+
connection.execute("BEGIN IMMEDIATE")
|
|
383
|
+
connection.executemany(
|
|
384
|
+
"UPDATE checkpoints SET status = 'restored', restored_at = ? WHERE checkpoint_id = ?",
|
|
385
|
+
[(restored_at, checkpoint_id) for checkpoint_id in checkpoint_ids],
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
run_id = records[0].run_id if all(
|
|
389
|
+
record.run_id == records[0].run_id for record in records
|
|
390
|
+
) else None
|
|
391
|
+
if run_id:
|
|
392
|
+
self.run_store.append_event(run_id, "checkpoint_restored", {
|
|
393
|
+
"checkpoint_ids": list(checkpoint_ids),
|
|
394
|
+
"paths": restored_paths,
|
|
395
|
+
})
|
|
396
|
+
return RestoreResult(checkpoint_ids, run_id, tuple(restored_paths))
|
|
397
|
+
|
|
398
|
+
def max_sequence(self) -> int:
|
|
399
|
+
"""The newest checkpoint's sequence; a later rewind undoes everything after it."""
|
|
400
|
+
with self._connect() as connection:
|
|
401
|
+
row = connection.execute("SELECT MAX(sequence) AS top FROM checkpoints").fetchone()
|
|
402
|
+
return int(row["top"] or 0)
|
|
403
|
+
|
|
404
|
+
def since(self, sequence: int, *, session_id: str | None = None) -> list[CheckpointRecord]:
|
|
405
|
+
"""Active checkpoints recorded after ``sequence``, newest first."""
|
|
406
|
+
clauses = ["status = 'active'", "sequence > ?"]
|
|
407
|
+
values: list[Any] = [int(sequence)]
|
|
408
|
+
if session_id:
|
|
409
|
+
clauses.append("session_id = ?")
|
|
410
|
+
values.append(session_id)
|
|
411
|
+
with self._connect() as connection:
|
|
412
|
+
rows = connection.execute(
|
|
413
|
+
f"SELECT * FROM checkpoints WHERE {' AND '.join(clauses)} ORDER BY sequence DESC",
|
|
414
|
+
values,
|
|
415
|
+
).fetchall()
|
|
416
|
+
return [self._row_to_checkpoint(connection, row) for row in rows]
|
|
417
|
+
|
|
418
|
+
def restore_since(
|
|
419
|
+
self,
|
|
420
|
+
sequence: int,
|
|
421
|
+
*,
|
|
422
|
+
session_id: str | None = None,
|
|
423
|
+
skip: Callable[[str], bool] = lambda _path: False,
|
|
424
|
+
) -> RestoreResult:
|
|
425
|
+
"""Undo every change recorded after ``sequence``, newest first, all or nothing.
|
|
426
|
+
|
|
427
|
+
``skip`` drops files that no longer have a place to be restored to —
|
|
428
|
+
an edit inside a task worktree that has since been removed, whose
|
|
429
|
+
effect on the user's files has its own checkpoint. Nothing to undo is
|
|
430
|
+
not an error: a point with no file changes after it rewinds to itself.
|
|
431
|
+
"""
|
|
432
|
+
records = self.since(sequence, session_id=session_id)
|
|
433
|
+
filtered = [replace(record, files=tuple(f for f in record.files if not skip(f.path)))
|
|
434
|
+
for record in records]
|
|
435
|
+
if any(record.files for record in filtered):
|
|
436
|
+
return self._restore(filtered)
|
|
437
|
+
if records:
|
|
438
|
+
restored_at = time.time()
|
|
439
|
+
with self._connect() as connection:
|
|
440
|
+
connection.execute("BEGIN IMMEDIATE")
|
|
441
|
+
connection.executemany(
|
|
442
|
+
"UPDATE checkpoints SET status = 'restored', restored_at = ? WHERE checkpoint_id = ?",
|
|
443
|
+
[(restored_at, record.checkpoint_id) for record in records],
|
|
444
|
+
)
|
|
445
|
+
return RestoreResult(tuple(record.checkpoint_id for record in records), None, ())
|
|
446
|
+
|
|
447
|
+
def restore_checkpoint(self, checkpoint_id: str) -> RestoreResult:
|
|
448
|
+
record = self.get(checkpoint_id)
|
|
449
|
+
if record is None or record.status != "active":
|
|
450
|
+
raise CheckpointNotFoundError(checkpoint_id)
|
|
451
|
+
return self._restore([record])
|
|
452
|
+
|
|
453
|
+
def restore_run(self, run_id: str) -> RestoreResult:
|
|
454
|
+
records = self.list(run_id=run_id, status="active", limit=10_000)
|
|
455
|
+
if not records:
|
|
456
|
+
raise CheckpointNotFoundError(run_id)
|
|
457
|
+
return self._restore(records)
|
|
458
|
+
|
|
459
|
+
def restore_latest_run(self, *, session_id: str | None = None) -> RestoreResult:
|
|
460
|
+
run_id = self.latest_run_id(session_id=session_id)
|
|
461
|
+
if not run_id:
|
|
462
|
+
raise CheckpointNotFoundError("No active run checkpoint found")
|
|
463
|
+
return self.restore_run(run_id)
|
|
464
|
+
|
|
465
|
+
def restore_latest(self, *, session_id: str | None = None) -> RestoreResult:
|
|
466
|
+
clauses = ["status = 'active'"]
|
|
467
|
+
values: list[Any] = []
|
|
468
|
+
if session_id:
|
|
469
|
+
clauses.append("session_id = ?")
|
|
470
|
+
values.append(session_id)
|
|
471
|
+
with self._connect() as connection:
|
|
472
|
+
row = connection.execute(
|
|
473
|
+
f"SELECT checkpoint_id, run_id FROM checkpoints "
|
|
474
|
+
f"WHERE {' AND '.join(clauses)} ORDER BY sequence DESC LIMIT 1",
|
|
475
|
+
values,
|
|
476
|
+
).fetchone()
|
|
477
|
+
if row is None:
|
|
478
|
+
raise CheckpointNotFoundError("No active checkpoint found")
|
|
479
|
+
if row["run_id"]:
|
|
480
|
+
return self.restore_run(row["run_id"])
|
|
481
|
+
return self.restore_checkpoint(row["checkpoint_id"])
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Ask another model — Claude, ChatGPT, Gemini — and bring its answer back.
|
|
2
|
+
|
|
3
|
+
Aria's own model does the work; another provider's model is useful when you want
|
|
4
|
+
a second opinion on a design, an unfamiliar API, or a bug the first model keeps
|
|
5
|
+
circling. `/consult claude <question>` sends the question (and whatever `@file`
|
|
6
|
+
references you put in it) to that model and files the answer in the conversation,
|
|
7
|
+
so the next thing you tell Aria can build on it.
|
|
8
|
+
|
|
9
|
+
Nothing goes out unless you type the command: the other model sees only the
|
|
10
|
+
question, never the conversation, the project or the tools.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Mapping, Optional, Tuple
|
|
16
|
+
|
|
17
|
+
CONSULT_SYSTEM = (
|
|
18
|
+
"You are being consulted by an AI coding assistant on behalf of a developer. "
|
|
19
|
+
"Answer the question directly and concisely, and say what you are unsure of. "
|
|
20
|
+
"You cannot see the project or the conversation; use only what is in the question."
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
#: Short names that mean a model. Only what is certain is built in; add the rest with
|
|
24
|
+
#: `/config set consult_aliases=...` or just type the full `provider/model`.
|
|
25
|
+
DEFAULT_ALIASES = {"claude": "anthropic/claude-sonnet-5-5"}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def resolve_model(name: str, config: Optional[Mapping] = None) -> Optional[str]:
|
|
29
|
+
"""`claude` or `provider/model` as a provider-qualified id, or None when it is neither."""
|
|
30
|
+
from aria_code.apps.cli.providers.chat_routing import model_provider
|
|
31
|
+
|
|
32
|
+
aliases = dict(DEFAULT_ALIASES)
|
|
33
|
+
custom = (config or {}).get("consult_aliases")
|
|
34
|
+
if isinstance(custom, Mapping):
|
|
35
|
+
aliases.update({str(k).lower(): str(v) for k, v in custom.items()})
|
|
36
|
+
model = aliases.get(name.strip().lower(), name.strip())
|
|
37
|
+
return model if model_provider(model) else None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def split_request(args: str) -> Tuple[str, str]:
|
|
41
|
+
"""`claude why does this race?` -> ("claude", "why does this race?")."""
|
|
42
|
+
parts = args.strip().split(maxsplit=1)
|
|
43
|
+
return (parts[0], parts[1].strip()) if len(parts) == 2 else ((parts[0], "") if parts else ("", ""))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def note_for_conversation(model: str, question: str, answer: str) -> str:
|
|
47
|
+
"""How the answer is filed in the conversation, so Aria's model can use it."""
|
|
48
|
+
return f"[second opinion from {model}]\nQuestion: {question}\n\nAnswer:\n{answer}"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def ask(model: str, question: str, config: Mapping, *, ollama_url: str = "http://localhost:11434") -> str:
|
|
52
|
+
"""The other model's answer to `question`; raises on a failed call."""
|
|
53
|
+
from aria_code.apps.cli.providers.runtime_bridge import make_provider_fn
|
|
54
|
+
|
|
55
|
+
call = make_provider_fn(
|
|
56
|
+
model=model, config=dict(config), api_url=None, ollama_url=ollama_url,
|
|
57
|
+
tool_schemas=[], system_override=CONSULT_SYSTEM,
|
|
58
|
+
)
|
|
59
|
+
result = await call(question, [])
|
|
60
|
+
if not result.get("success", True):
|
|
61
|
+
raise RuntimeError(result.get("error") or "the model did not answer")
|
|
62
|
+
answer = str(result.get("response") or "").strip()
|
|
63
|
+
if not answer:
|
|
64
|
+
raise RuntimeError("the model returned an empty answer")
|
|
65
|
+
return answer
|