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,326 @@
|
|
|
1
|
+
"""Stateless helpers lifted out of aria_cli.py.
|
|
2
|
+
|
|
3
|
+
These twelve functions never touched aria_cli's module state — no console, no
|
|
4
|
+
HAS_RICH, no tool registry — yet twelve command mixins reached back into a
|
|
5
|
+
7000-line module to call them, because that is simply where they happened to
|
|
6
|
+
be defined. Nothing about them needs to live there.
|
|
7
|
+
|
|
8
|
+
aria_cli re-exports them under their original names, so its own callers and the
|
|
9
|
+
globals-rebind for the modules that still rely on it are unaffected.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import pathlib
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"detect_ollama_models",
|
|
20
|
+
"detect_ollama_models_rich",
|
|
21
|
+
"_load_project_context",
|
|
22
|
+
"_display_value",
|
|
23
|
+
"_chart_display_label",
|
|
24
|
+
"_chart_period_from_ta_days",
|
|
25
|
+
"_copy_text_to_clipboard",
|
|
26
|
+
"_reveal_path_in_finder",
|
|
27
|
+
"_open_path_or_url",
|
|
28
|
+
"_extract_code_block",
|
|
29
|
+
"_clean_tool_error_message",
|
|
30
|
+
"_fuzzy_match",
|
|
31
|
+
"_is_ashare_symbol",
|
|
32
|
+
"format_sparkline",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Per directory: the AGENTS.md family (the convention Codex and other agents
|
|
37
|
+
# share) and Aria's own ARIA.md are both read; CLAUDE.md only when neither is
|
|
38
|
+
# there. AGENTS.override.md stands in for AGENTS.md, as in Codex.
|
|
39
|
+
_AGENTS_NAMES = ("AGENTS.override.md", "AGENTS.md")
|
|
40
|
+
_ARIA_NAMES = ("ARIA.md", ".aria.md")
|
|
41
|
+
_FALLBACK_NAMES = ("CLAUDE.md",)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _project_rule_files(directory: pathlib.Path) -> list[pathlib.Path]:
|
|
45
|
+
picked = []
|
|
46
|
+
for family in (_AGENTS_NAMES, _ARIA_NAMES):
|
|
47
|
+
hit = next((directory / n for n in family if (directory / n).is_file()), None)
|
|
48
|
+
if hit:
|
|
49
|
+
picked.append(hit)
|
|
50
|
+
if not picked:
|
|
51
|
+
picked = [directory / n for n in _FALLBACK_NAMES if (directory / n).is_file()][:1]
|
|
52
|
+
return picked
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _load_project_context() -> str:
|
|
56
|
+
"""Load AGENTS.md / ARIA.md / CLAUDE.md by walking up from cwd.
|
|
57
|
+
|
|
58
|
+
Only ARIA.md and CLAUDE.md were read, so a repository set up for Codex
|
|
59
|
+
and other agents through AGENTS.md gave Aria none of its rules. The walk
|
|
60
|
+
now stops at the repository root (a parent of the repository is not part
|
|
61
|
+
of the project), files nearer the working directory come first and get
|
|
62
|
+
first claim on the size cap, and ~/.arthera/ARIA.md comes last. It came
|
|
63
|
+
first, so a long global profile could crowd the project's rules out.
|
|
64
|
+
"""
|
|
65
|
+
_MAX_BYTES = 12288
|
|
66
|
+
_MAX_LEVELS = 5
|
|
67
|
+
|
|
68
|
+
home = pathlib.Path.home()
|
|
69
|
+
cwd = pathlib.Path.cwd().resolve()
|
|
70
|
+
|
|
71
|
+
found: list[tuple[pathlib.Path, str]] = [] # nearest first
|
|
72
|
+
seen_text: set[str] = set()
|
|
73
|
+
|
|
74
|
+
def add(path: pathlib.Path) -> None:
|
|
75
|
+
try:
|
|
76
|
+
content = path.read_text(encoding="utf-8")
|
|
77
|
+
except Exception:
|
|
78
|
+
return
|
|
79
|
+
key = content.strip()
|
|
80
|
+
if key and key not in seen_text: # a CLAUDE.md copied to AGENTS.md, a symlink
|
|
81
|
+
seen_text.add(key)
|
|
82
|
+
found.append((path, content))
|
|
83
|
+
|
|
84
|
+
current = cwd
|
|
85
|
+
for _ in range(_MAX_LEVELS):
|
|
86
|
+
for path in _project_rule_files(current):
|
|
87
|
+
add(path)
|
|
88
|
+
if current == home or current.parent == current or (current / ".git").exists():
|
|
89
|
+
break
|
|
90
|
+
current = current.parent
|
|
91
|
+
|
|
92
|
+
# Global user file — lowest priority; /memory edit global edits it.
|
|
93
|
+
from aria_code.account_session import profile_path, read_config, account_id
|
|
94
|
+
_global_aria = profile_path()
|
|
95
|
+
# Signed-in personal facts come from the cloud snapshot/outbox, so a fact
|
|
96
|
+
# deleted on Web cannot be reintroduced by an old local profile file.
|
|
97
|
+
_include_personal_file = account_id(read_config()) is None
|
|
98
|
+
if _include_personal_file and _global_aria.is_file() and not any(f == _global_aria for f, _ in found):
|
|
99
|
+
add(_global_aria)
|
|
100
|
+
|
|
101
|
+
if not found:
|
|
102
|
+
return ""
|
|
103
|
+
|
|
104
|
+
blocks: list[str] = []
|
|
105
|
+
total = 0
|
|
106
|
+
for fpath, content in found:
|
|
107
|
+
rel = fpath.relative_to(home) if fpath.is_relative_to(home) else fpath
|
|
108
|
+
snippet = content[:(_MAX_BYTES - total)]
|
|
109
|
+
blocks.append(f"### {rel}\n{snippet}")
|
|
110
|
+
total += len(snippet)
|
|
111
|
+
if total >= _MAX_BYTES:
|
|
112
|
+
break
|
|
113
|
+
|
|
114
|
+
header = ("\n\n## Project Context\n"
|
|
115
|
+
"Where these files disagree, the one listed first (nearest the working directory) wins.\n\n")
|
|
116
|
+
return header + "\n\n".join(blocks)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _display_value(value, digits: int = 2, suffix: str = "") -> str:
|
|
120
|
+
try:
|
|
121
|
+
if value in (None, "", "N/A", "-", "nan"):
|
|
122
|
+
return "—"
|
|
123
|
+
if isinstance(value, (int, float)):
|
|
124
|
+
return f"{float(value):,.{digits}f}{suffix}"
|
|
125
|
+
return str(value)
|
|
126
|
+
except Exception:
|
|
127
|
+
return "—"
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _chart_display_label(raw: str, resolved: str, result: dict | None = None) -> str:
|
|
131
|
+
result = result or {}
|
|
132
|
+
name = str(result.get("name") or result.get("display_name") or "").strip()
|
|
133
|
+
resolved = str(resolved or "").strip().upper()
|
|
134
|
+
raw_label = str(raw or "").strip().upper()
|
|
135
|
+
if name and name.upper() != resolved:
|
|
136
|
+
return f"{name} ({resolved})"
|
|
137
|
+
if raw_label and raw_label != resolved and not raw_label.startswith(resolved):
|
|
138
|
+
return f"{raw_label} ({resolved})"
|
|
139
|
+
return resolved or raw_label or "chart"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _chart_period_from_ta_days(days: int) -> str:
|
|
143
|
+
try:
|
|
144
|
+
d = int(days)
|
|
145
|
+
except Exception:
|
|
146
|
+
return "1y"
|
|
147
|
+
if d <= 45:
|
|
148
|
+
return "1mo"
|
|
149
|
+
if d <= 110:
|
|
150
|
+
return "3mo"
|
|
151
|
+
if d <= 220:
|
|
152
|
+
return "6mo"
|
|
153
|
+
if d <= 430:
|
|
154
|
+
return "1y"
|
|
155
|
+
if d <= 800:
|
|
156
|
+
return "2y"
|
|
157
|
+
return "3y"
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _copy_text_to_clipboard(text: str) -> tuple[bool, str]:
|
|
161
|
+
try:
|
|
162
|
+
import subprocess as _sp
|
|
163
|
+
_sp.run(["pbcopy"], input=text.encode("utf-8"), check=True, timeout=3)
|
|
164
|
+
return True, ""
|
|
165
|
+
except Exception as exc:
|
|
166
|
+
return False, str(exc)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _reveal_path_in_finder(path: str) -> tuple[bool, str]:
|
|
170
|
+
try:
|
|
171
|
+
import subprocess as _sp
|
|
172
|
+
_sp.Popen(["open", "-R", path])
|
|
173
|
+
return True, ""
|
|
174
|
+
except Exception as exc:
|
|
175
|
+
return False, str(exc)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _open_path_or_url(target: str) -> tuple[bool, str]:
|
|
179
|
+
try:
|
|
180
|
+
import subprocess as _sp
|
|
181
|
+
_sp.Popen(["open", target])
|
|
182
|
+
return True, ""
|
|
183
|
+
except Exception as exc:
|
|
184
|
+
return False, str(exc)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _extract_code_block(text: str) -> Optional[str]:
|
|
188
|
+
"""Extract the first code block from markdown-formatted text."""
|
|
189
|
+
import re
|
|
190
|
+
# Match ```python ... ``` or ``` ... ```
|
|
191
|
+
pattern = r'```(?:python|py)?\s*\n(.*?)```'
|
|
192
|
+
match = re.search(pattern, text, re.DOTALL)
|
|
193
|
+
if match:
|
|
194
|
+
return match.group(1).strip()
|
|
195
|
+
# Fallback: try to find any code block
|
|
196
|
+
pattern2 = r'```\w*\s*\n(.*?)```'
|
|
197
|
+
match2 = re.search(pattern2, text, re.DOTALL)
|
|
198
|
+
if match2:
|
|
199
|
+
return match2.group(1).strip()
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _clean_tool_error_message(error: object) -> str:
|
|
204
|
+
from ui.render.output import clean_tool_error_message as _ctm
|
|
205
|
+
return _ctm(error)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _fuzzy_match(query: str, candidates: list, max_results: int = 3) -> list:
|
|
209
|
+
"""Find closest matches using simple edit distance."""
|
|
210
|
+
def _edit_dist(a, b):
|
|
211
|
+
if len(a) > len(b):
|
|
212
|
+
a, b = b, a
|
|
213
|
+
dists = range(len(a) + 1)
|
|
214
|
+
for j, cb in enumerate(b):
|
|
215
|
+
new_dists = [j + 1]
|
|
216
|
+
for i, ca in enumerate(a):
|
|
217
|
+
cost = 0 if ca == cb else 1
|
|
218
|
+
new_dists.append(min(new_dists[-1] + 1, dists[i + 1] + 1, dists[i] + cost))
|
|
219
|
+
dists = new_dists
|
|
220
|
+
return dists[-1]
|
|
221
|
+
|
|
222
|
+
scored = [(c, _edit_dist(query.lower(), c.lower())) for c in candidates]
|
|
223
|
+
scored.sort(key=lambda x: x[1])
|
|
224
|
+
# Only suggest if edit distance is reasonable (< half the length)
|
|
225
|
+
threshold = max(3, len(query) // 2)
|
|
226
|
+
return [c for c, d in scored[:max_results] if d <= threshold]
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _is_ashare_symbol(symbol: str) -> bool:
|
|
230
|
+
"""Quick check whether a symbol looks like a Chinese A-share code."""
|
|
231
|
+
s = symbol.strip().lower()
|
|
232
|
+
return (
|
|
233
|
+
s.startswith("sh") or s.startswith("sz")
|
|
234
|
+
or (len(s) == 6 and s.isdigit())
|
|
235
|
+
or s.endswith(".ss") or s.endswith(".sz")
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def format_sparkline(prices: list, width: int = 30) -> str:
|
|
240
|
+
"""Generate Unicode sparkline from price data."""
|
|
241
|
+
if not prices or len(prices) < 2:
|
|
242
|
+
return ""
|
|
243
|
+
blocks = "▁▂▃▄▅▆▇█"
|
|
244
|
+
mn, mx = min(prices), max(prices)
|
|
245
|
+
rng = mx - mn or 1
|
|
246
|
+
result = ""
|
|
247
|
+
step = max(1, len(prices) // width)
|
|
248
|
+
for i in range(0, len(prices), step):
|
|
249
|
+
idx = int((prices[i] - mn) / rng * (len(blocks) - 1))
|
|
250
|
+
result += blocks[idx]
|
|
251
|
+
return result[:width]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def detect_ollama_models(ollama_url: str = "http://localhost:11434") -> list:
|
|
255
|
+
"""Query Ollama /api/tags and return list of available model names.
|
|
256
|
+
|
|
257
|
+
Always bypasses HTTP_PROXY so localhost is reached directly even when a
|
|
258
|
+
system proxy (VPN / clash / surge) is active.
|
|
259
|
+
"""
|
|
260
|
+
import urllib.request
|
|
261
|
+
# Force direct connection — bypass any HTTP_PROXY / HTTPS_PROXY env vars
|
|
262
|
+
_opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
|
|
263
|
+
try:
|
|
264
|
+
with _opener.open(f"{ollama_url}/api/tags", timeout=5) as r:
|
|
265
|
+
data = json.loads(r.read())
|
|
266
|
+
return [m["name"] for m in data.get("models", [])]
|
|
267
|
+
except Exception:
|
|
268
|
+
# Also try 127.0.0.1 if hostname is "localhost" (IPv6 resolution fallback)
|
|
269
|
+
if "localhost" in ollama_url:
|
|
270
|
+
try:
|
|
271
|
+
fallback = ollama_url.replace("localhost", "127.0.0.1")
|
|
272
|
+
with _opener.open(f"{fallback}/api/tags", timeout=5) as r:
|
|
273
|
+
data = json.loads(r.read())
|
|
274
|
+
return [m["name"] for m in data.get("models", [])]
|
|
275
|
+
except Exception:
|
|
276
|
+
pass
|
|
277
|
+
return []
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def detect_ollama_models_rich(ollama_url: str = "http://localhost:11434") -> tuple:
|
|
281
|
+
"""Return (models_list, error_str) where each entry in models_list is a dict:
|
|
282
|
+
{"name": str, "size_label": str, "family": str, "quant": str,
|
|
283
|
+
"execution": "local" | "remote", "remote_host": str,
|
|
284
|
+
"context_window": int, "capabilities": list[str]}
|
|
285
|
+
error_str is None on success, or a short human-readable reason on failure.
|
|
286
|
+
"""
|
|
287
|
+
import urllib.request
|
|
288
|
+
_opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
|
|
289
|
+
|
|
290
|
+
def _try(url: str):
|
|
291
|
+
with _opener.open(f"{url}/api/tags", timeout=5) as r:
|
|
292
|
+
return json.loads(r.read())
|
|
293
|
+
|
|
294
|
+
data = None
|
|
295
|
+
last_err = None
|
|
296
|
+
for u in [ollama_url] + ([ollama_url.replace("localhost", "127.0.0.1")]
|
|
297
|
+
if "localhost" in ollama_url else []):
|
|
298
|
+
try:
|
|
299
|
+
data = _try(u)
|
|
300
|
+
break
|
|
301
|
+
except OSError as e:
|
|
302
|
+
last_err = str(e)
|
|
303
|
+
except Exception as e:
|
|
304
|
+
last_err = str(e)
|
|
305
|
+
|
|
306
|
+
if data is None:
|
|
307
|
+
return [], last_err or "connection failed"
|
|
308
|
+
|
|
309
|
+
results = []
|
|
310
|
+
for m in data.get("models", []):
|
|
311
|
+
det = m.get("details", {})
|
|
312
|
+
size = det.get("parameter_size", "")
|
|
313
|
+
fam = det.get("family", "")
|
|
314
|
+
qnt = det.get("quantization_level", "")
|
|
315
|
+
results.append({
|
|
316
|
+
"name": m["name"],
|
|
317
|
+
"size_label": size, # e.g. "1.5B", "7B", "671.0B"
|
|
318
|
+
"family": fam, # e.g. "qwen2", "deepseek2"
|
|
319
|
+
"quant": qnt, # e.g. "Q4_K_M", "MXFP4"
|
|
320
|
+
"execution": "remote" if m.get("remote_host") else "local",
|
|
321
|
+
"remote_model": m.get("remote_model", ""),
|
|
322
|
+
"remote_host": m.get("remote_host", ""),
|
|
323
|
+
"context_window": int(det.get("context_length") or 0),
|
|
324
|
+
"capabilities": list(m.get("capabilities") or []),
|
|
325
|
+
})
|
|
326
|
+
return results, None
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Aria Code lifecycle hooks — JSON-configurable, shell-executable.
|
|
2
|
+
|
|
3
|
+
Config file: ~/.arthera/hooks.json
|
|
4
|
+
Project-local override: .aria/hooks.json (takes precedence)
|
|
5
|
+
|
|
6
|
+
Schema
|
|
7
|
+
------
|
|
8
|
+
{
|
|
9
|
+
"PreToolUse": [{"tool": "run_command", "command": "echo $ARIA_TOOL"}],
|
|
10
|
+
"PostToolUse": [{"command": "notify-send 'done'"}],
|
|
11
|
+
"ResponseDone": [{"command": "afplay /System/Sounds/Glass.aiff"}],
|
|
12
|
+
"SessionStart": [{"command": "echo starting $ARIA_SESSION"}],
|
|
13
|
+
"SessionEnd": [{"command": "echo ended"}]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Each hook entry:
|
|
17
|
+
command — shell command to execute (required)
|
|
18
|
+
tool — if set, only fires when tool name matches (PreToolUse / PostToolUse)
|
|
19
|
+
timeout — seconds before the hook is killed (default 10)
|
|
20
|
+
blocking — if true AND exit code != 0, execution is blocked (PreToolUse only)
|
|
21
|
+
|
|
22
|
+
Env vars injected into every hook:
|
|
23
|
+
ARIA_EVENT — hook event name
|
|
24
|
+
ARIA_TOOL — tool name (Pre/PostToolUse only)
|
|
25
|
+
ARIA_TOOL_PARAMS — JSON-encoded params (Pre/PostToolUse only)
|
|
26
|
+
ARIA_RESULT — JSON-encoded result (PostToolUse only)
|
|
27
|
+
ARIA_RESPONSE — first 500 chars of response (ResponseDone)
|
|
28
|
+
ARIA_SESSION — session ID
|
|
29
|
+
"""
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import json
|
|
33
|
+
import logging
|
|
34
|
+
import os
|
|
35
|
+
import subprocess
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
from typing import Optional
|
|
38
|
+
|
|
39
|
+
from aria_code.apps.cli.config_paths import resolve_config_dir
|
|
40
|
+
|
|
41
|
+
logger = logging.getLogger(__name__)
|
|
42
|
+
|
|
43
|
+
_CONFIG_DIR = resolve_config_dir()
|
|
44
|
+
_GLOBAL_HOOKS_FILE = _CONFIG_DIR / "hooks.json"
|
|
45
|
+
_LOCAL_HOOKS_FILE = Path.cwd() / ".aria" / "hooks.json"
|
|
46
|
+
|
|
47
|
+
_VALID_EVENTS = frozenset([
|
|
48
|
+
"PreToolUse", "PostToolUse",
|
|
49
|
+
"ResponseDone",
|
|
50
|
+
"SessionStart", "SessionEnd",
|
|
51
|
+
])
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def load_hooks() -> dict:
|
|
55
|
+
"""Load and merge global + project-local hooks config."""
|
|
56
|
+
merged: dict[str, list] = {e: [] for e in _VALID_EVENTS}
|
|
57
|
+
|
|
58
|
+
for path in (_GLOBAL_HOOKS_FILE, _LOCAL_HOOKS_FILE):
|
|
59
|
+
if path.exists():
|
|
60
|
+
try:
|
|
61
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
62
|
+
for event, entries in data.items():
|
|
63
|
+
if event in _VALID_EVENTS and isinstance(entries, list):
|
|
64
|
+
merged[event].extend(entries)
|
|
65
|
+
except Exception as exc:
|
|
66
|
+
logger.debug("hooks.json parse error (%s): %s", path, exc)
|
|
67
|
+
|
|
68
|
+
return merged
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def fire(
|
|
72
|
+
event: str,
|
|
73
|
+
*,
|
|
74
|
+
tool: Optional[str] = None,
|
|
75
|
+
params: Optional[dict] = None,
|
|
76
|
+
result: Optional[dict] = None,
|
|
77
|
+
response: str = "",
|
|
78
|
+
session_id: str = "",
|
|
79
|
+
hooks: Optional[dict] = None,
|
|
80
|
+
) -> bool:
|
|
81
|
+
"""Fire all matching hooks for an event.
|
|
82
|
+
|
|
83
|
+
Returns False if any *blocking* PreToolUse hook exits non-zero
|
|
84
|
+
(meaning the tool call should be suppressed). Returns True otherwise.
|
|
85
|
+
"""
|
|
86
|
+
if hooks is None:
|
|
87
|
+
hooks = load_hooks()
|
|
88
|
+
|
|
89
|
+
entries = hooks.get(event, [])
|
|
90
|
+
if not entries:
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
base_env = dict(os.environ)
|
|
94
|
+
base_env["ARIA_EVENT"] = event
|
|
95
|
+
base_env["ARIA_SESSION"] = session_id or ""
|
|
96
|
+
if tool:
|
|
97
|
+
base_env["ARIA_TOOL"] = tool
|
|
98
|
+
if params is not None:
|
|
99
|
+
base_env["ARIA_TOOL_PARAMS"] = json.dumps(params, ensure_ascii=False)[:2000]
|
|
100
|
+
if result is not None:
|
|
101
|
+
base_env["ARIA_RESULT"] = json.dumps(result, ensure_ascii=False)[:2000]
|
|
102
|
+
if response:
|
|
103
|
+
base_env["ARIA_RESPONSE"] = response[:500]
|
|
104
|
+
|
|
105
|
+
blocked = False
|
|
106
|
+
for entry in entries:
|
|
107
|
+
if not isinstance(entry, dict):
|
|
108
|
+
continue
|
|
109
|
+
cmd = entry.get("command", "").strip()
|
|
110
|
+
if not cmd:
|
|
111
|
+
continue
|
|
112
|
+
|
|
113
|
+
# Tool filter: skip if hook is scoped to a different tool
|
|
114
|
+
if entry.get("tool") and tool and entry["tool"] != tool:
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
timeout = int(entry.get("timeout", 10))
|
|
118
|
+
is_blocking = bool(entry.get("blocking", False))
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
proc = subprocess.run(
|
|
122
|
+
cmd,
|
|
123
|
+
shell=True,
|
|
124
|
+
env=base_env,
|
|
125
|
+
timeout=timeout,
|
|
126
|
+
capture_output=True,
|
|
127
|
+
text=True,
|
|
128
|
+
)
|
|
129
|
+
if is_blocking and proc.returncode != 0 and event == "PreToolUse":
|
|
130
|
+
logger.info(
|
|
131
|
+
"Blocking hook vetoed tool '%s': exit %d — %s",
|
|
132
|
+
tool, proc.returncode, proc.stderr[:120],
|
|
133
|
+
)
|
|
134
|
+
blocked = True
|
|
135
|
+
except subprocess.TimeoutExpired:
|
|
136
|
+
logger.debug("Hook timed out after %ds: %s", timeout, cmd[:60])
|
|
137
|
+
except Exception as exc:
|
|
138
|
+
logger.debug("Hook error: %s", exc)
|
|
139
|
+
|
|
140
|
+
return not blocked
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def list_hooks() -> list[dict]:
|
|
144
|
+
"""Return a flat list of configured hooks for display."""
|
|
145
|
+
hooks = load_hooks()
|
|
146
|
+
rows = []
|
|
147
|
+
for event, entries in hooks.items():
|
|
148
|
+
for entry in entries:
|
|
149
|
+
if isinstance(entry, dict) and entry.get("command"):
|
|
150
|
+
rows.append({
|
|
151
|
+
"event": event,
|
|
152
|
+
"tool": entry.get("tool", "*"),
|
|
153
|
+
"command": entry["command"][:80],
|
|
154
|
+
"blocking": entry.get("blocking", False),
|
|
155
|
+
"timeout": entry.get("timeout", 10),
|
|
156
|
+
})
|
|
157
|
+
return rows
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def hooks_file_path(scope: str = "global") -> Path:
|
|
161
|
+
"""Return the hooks.json path for a given scope."""
|
|
162
|
+
if scope == "local":
|
|
163
|
+
return Path.cwd() / ".aria" / "hooks.json"
|
|
164
|
+
return _GLOBAL_HOOKS_FILE
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def create_example_hooks(path: Path) -> None:
|
|
168
|
+
"""Write an annotated example hooks.json if it doesn't exist."""
|
|
169
|
+
if path.exists():
|
|
170
|
+
return
|
|
171
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
172
|
+
example = {
|
|
173
|
+
"_comment": "Aria Code hooks — schema: https://github.com/artheras/aria-code/blob/main/src/aria_code/apps/cli/hooks.py",
|
|
174
|
+
"PreToolUse": [],
|
|
175
|
+
"PostToolUse": [],
|
|
176
|
+
"ResponseDone": [],
|
|
177
|
+
"SessionStart": [],
|
|
178
|
+
"SessionEnd": [],
|
|
179
|
+
}
|
|
180
|
+
path.write_text(json.dumps(example, indent=2, ensure_ascii=False), encoding="utf-8")
|