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
aria_code/ui/mentions.py
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""One search behind "@": files, folders, market assets and saved resources.
|
|
2
|
+
|
|
3
|
+
"@" opened on a list of kinds — file:, folder:, asset:, portfolio: … — and a
|
|
4
|
+
file only appeared once a path character was typed, so attaching src/fx.py
|
|
5
|
+
took "@", "file:", then the path. Codex's "@" goes straight to results across
|
|
6
|
+
files, folders and plugins. Here "@fx" lists fx.py, test_fx.py and any asset,
|
|
7
|
+
strategy or report that matches, each labelled with its kind; "@file:" and the
|
|
8
|
+
other kind prefixes still narrow the list to one kind.
|
|
9
|
+
|
|
10
|
+
The inserted text is the canonical reference (@file:src/fx.py, @asset:AAPL),
|
|
11
|
+
so references.py resolves it unchanged. Nothing here imports prompt_toolkit.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import subprocess
|
|
18
|
+
import time
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Iterable
|
|
22
|
+
|
|
23
|
+
from aria_code.packages.aria_services.references import reference_search_roots
|
|
24
|
+
|
|
25
|
+
# Directories a walk never enters when the workspace is not a git repository.
|
|
26
|
+
_SKIP_DIRS = frozenset({
|
|
27
|
+
".git", ".hg", ".svn", ".venv", "venv", "env", "node_modules", "__pycache__", ".mypy_cache",
|
|
28
|
+
".pytest_cache", ".ruff_cache", ".tox", "dist", "build", ".next", ".idea", ".vscode", "target",
|
|
29
|
+
})
|
|
30
|
+
MAX_INDEXED_FILES = 20000
|
|
31
|
+
INDEX_TTL_SECONDS = 30.0
|
|
32
|
+
RESOURCE_KINDS = ("portfolio", "strategy", "dataset", "run", "report")
|
|
33
|
+
# Within one match quality, this order breaks ties. A saved strategy or report
|
|
34
|
+
# is named on purpose, so it ranks above the file behind it; an asset ranks
|
|
35
|
+
# first only when the query is typed like a ticker ("@FX", not "@fx").
|
|
36
|
+
_KIND_ORDER = {"strategy": 1, "portfolio": 2, "report": 3, "dataset": 4, "run": 5, "file": 6, "folder": 7}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class Mention:
|
|
41
|
+
kind: str
|
|
42
|
+
value: str # what follows "kind:" — a path, a symbol, a name
|
|
43
|
+
score: int # lower is better
|
|
44
|
+
matched: tuple[int, ...] = () # positions in `label` to highlight
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def label(self) -> str:
|
|
48
|
+
return self.value + ("/" if self.kind == "folder" else "")
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def insert_text(self) -> str:
|
|
52
|
+
value = f'"{self.value}"' if any(ch.isspace() for ch in self.value) else self.value
|
|
53
|
+
return f"{self.kind}:{value}"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _match(query: str, text: str) -> tuple[int, tuple[int, ...]] | None:
|
|
57
|
+
"""(score, positions) of query in text, or None. Case-insensitive."""
|
|
58
|
+
if not query:
|
|
59
|
+
return 50, ()
|
|
60
|
+
q, t = query.lower(), text.lower()
|
|
61
|
+
if t == q:
|
|
62
|
+
return 0, tuple(range(len(text)))
|
|
63
|
+
if t.startswith(q):
|
|
64
|
+
return 10, tuple(range(len(query)))
|
|
65
|
+
at = t.find(q)
|
|
66
|
+
if at >= 0:
|
|
67
|
+
return 20 + min(at, 9), tuple(range(at, at + len(query)))
|
|
68
|
+
positions, i = [], 0
|
|
69
|
+
for index, ch in enumerate(t):
|
|
70
|
+
if i < len(q) and ch == q[i]:
|
|
71
|
+
positions.append(index)
|
|
72
|
+
i += 1
|
|
73
|
+
if i == len(q):
|
|
74
|
+
spread = positions[-1] - positions[0]
|
|
75
|
+
return 40 + min(spread, 29), tuple(positions)
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _match_path(query: str, path: str) -> tuple[int, tuple[int, ...]] | None:
|
|
80
|
+
"""Prefer the file name; fall back to the whole relative path."""
|
|
81
|
+
name_start = path.rfind("/") + 1
|
|
82
|
+
name_hit = _match(query, path[name_start:])
|
|
83
|
+
if name_hit is not None:
|
|
84
|
+
score, positions = name_hit
|
|
85
|
+
return score, tuple(name_start + p for p in positions)
|
|
86
|
+
path_hit = _match(query, path)
|
|
87
|
+
if path_hit is not None:
|
|
88
|
+
return path_hit[0] + 5, path_hit[1]
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class MentionIndex:
|
|
93
|
+
"""Searches everything "@" can attach, for one workspace."""
|
|
94
|
+
|
|
95
|
+
def __init__(self, workspace: Path | str, *, output_root: Path | str | None = None,
|
|
96
|
+
symbols: Iterable[str] = ()):
|
|
97
|
+
self.workspace = Path(workspace).expanduser().resolve()
|
|
98
|
+
self.output_root = Path(output_root).expanduser().resolve() if output_root else None
|
|
99
|
+
self.symbols = sorted({str(s).upper() for s in symbols if str(s).strip()})
|
|
100
|
+
self._files: list[str] = []
|
|
101
|
+
self._indexed_at = 0.0
|
|
102
|
+
|
|
103
|
+
# ── the file list ────────────────────────────────────────────────────────
|
|
104
|
+
def files(self) -> list[str]:
|
|
105
|
+
"""Workspace-relative file paths, .gitignore respected when in a repository."""
|
|
106
|
+
if not self._files or time.monotonic() - self._indexed_at > INDEX_TTL_SECONDS:
|
|
107
|
+
self._files = self._git_files() or self._walk_files()
|
|
108
|
+
self._indexed_at = time.monotonic()
|
|
109
|
+
return self._files
|
|
110
|
+
|
|
111
|
+
def _git_files(self) -> list[str]:
|
|
112
|
+
try:
|
|
113
|
+
done = subprocess.run(
|
|
114
|
+
["git", "ls-files", "--cached", "--others", "--exclude-standard"],
|
|
115
|
+
cwd=self.workspace, capture_output=True, text=True, timeout=3,
|
|
116
|
+
)
|
|
117
|
+
except (OSError, subprocess.SubprocessError):
|
|
118
|
+
return []
|
|
119
|
+
if done.returncode != 0:
|
|
120
|
+
return []
|
|
121
|
+
return [line for line in done.stdout.splitlines() if line][:MAX_INDEXED_FILES]
|
|
122
|
+
|
|
123
|
+
def _walk_files(self) -> list[str]:
|
|
124
|
+
found: list[str] = []
|
|
125
|
+
for root, dirs, names in os.walk(self.workspace):
|
|
126
|
+
dirs[:] = sorted(d for d in dirs if d not in _SKIP_DIRS and not d.startswith("."))
|
|
127
|
+
rel_root = os.path.relpath(root, self.workspace)
|
|
128
|
+
for name in sorted(names):
|
|
129
|
+
if name.startswith("."):
|
|
130
|
+
continue
|
|
131
|
+
found.append(name if rel_root == "." else f"{rel_root}/{name}".replace(os.sep, "/"))
|
|
132
|
+
if len(found) >= MAX_INDEXED_FILES:
|
|
133
|
+
return found
|
|
134
|
+
return found
|
|
135
|
+
|
|
136
|
+
def folders(self) -> list[str]:
|
|
137
|
+
seen: dict[str, None] = {}
|
|
138
|
+
for path in self.files():
|
|
139
|
+
parts = path.split("/")[:-1]
|
|
140
|
+
for depth in range(1, len(parts) + 1):
|
|
141
|
+
seen["/".join(parts[:depth])] = None
|
|
142
|
+
return list(seen)
|
|
143
|
+
|
|
144
|
+
def recent_files(self, limit: int = 5) -> list[str]:
|
|
145
|
+
stamped = []
|
|
146
|
+
for path in self.files()[:MAX_INDEXED_FILES]:
|
|
147
|
+
try:
|
|
148
|
+
stamped.append((os.stat(self.workspace / path).st_mtime, path))
|
|
149
|
+
except OSError:
|
|
150
|
+
continue
|
|
151
|
+
return [path for _, path in sorted(stamped, reverse=True)[:limit]]
|
|
152
|
+
|
|
153
|
+
def resources(self, kind: str) -> list[str]:
|
|
154
|
+
names: dict[str, None] = {}
|
|
155
|
+
for root in reference_search_roots(kind, self.workspace, self.output_root):
|
|
156
|
+
if not root.is_dir():
|
|
157
|
+
continue
|
|
158
|
+
try:
|
|
159
|
+
for path in root.rglob("*"):
|
|
160
|
+
if path.is_file() and not any(p.startswith(".") for p in path.relative_to(root).parts):
|
|
161
|
+
names[path.stem] = None
|
|
162
|
+
if len(names) >= 200:
|
|
163
|
+
break
|
|
164
|
+
except OSError:
|
|
165
|
+
continue
|
|
166
|
+
return list(names)
|
|
167
|
+
|
|
168
|
+
# ── search ───────────────────────────────────────────────────────────────
|
|
169
|
+
def search(self, query: str, *, kind: str | None = None, limit: int = 30) -> list[Mention]:
|
|
170
|
+
"""Matches for `query`, best first; only `kind` when one is given."""
|
|
171
|
+
found: list[Mention] = []
|
|
172
|
+
|
|
173
|
+
def add(k: str, values: Iterable[str], matcher) -> None:
|
|
174
|
+
if kind and k != kind:
|
|
175
|
+
return
|
|
176
|
+
for value in values:
|
|
177
|
+
hit = matcher(query, value)
|
|
178
|
+
if hit is not None:
|
|
179
|
+
found.append(Mention(k, value, hit[0], hit[1]))
|
|
180
|
+
|
|
181
|
+
add("file", self.files(), _match_path)
|
|
182
|
+
add("folder", self.folders(), _match_path)
|
|
183
|
+
# Tickers by exact, prefix or substring only: "fx" scattered through
|
|
184
|
+
# NFLX is not a way anyone looks for Netflix.
|
|
185
|
+
add("asset", self.symbols, lambda q, v: (h if (h := _match(q, v)) and h[0] < 40 else None))
|
|
186
|
+
if query and _looks_like_symbol(query) and query.upper() not in self.symbols and kind in (None, "asset"):
|
|
187
|
+
found.append(Mention("asset", query.upper(), 30, tuple(range(len(query)))))
|
|
188
|
+
for resource in RESOURCE_KINDS:
|
|
189
|
+
add(resource, self.resources(resource), _match)
|
|
190
|
+
asset_rank = 0 if _looks_like_symbol(query) else 8
|
|
191
|
+
found.sort(key=lambda m: (m.score, asset_rank if m.kind == "asset" else _KIND_ORDER.get(m.kind, 9),
|
|
192
|
+
len(m.value), m.value))
|
|
193
|
+
# Letters scattered through a long path ("AAP" in providers/llm/ollama.py)
|
|
194
|
+
# are noise once there is a popup's worth of closer matches.
|
|
195
|
+
if sum(1 for m in found if m.score < 40) >= 8:
|
|
196
|
+
found = [m for m in found if m.score < 40]
|
|
197
|
+
return found[:limit]
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _looks_like_symbol(text: str) -> bool:
|
|
201
|
+
"""A ticker someone is typing: "AAPL", "0700.HK", "BTC-USD" — not "fx" or "readme"."""
|
|
202
|
+
raw = text.strip()
|
|
203
|
+
return 1 <= len(raw) <= 12 and raw.upper() == raw and any(ch.isalnum() for ch in raw) and " " not in raw
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
__all__ = ["Mention", "MentionIndex"]
|
aria_code/ui/picker.py
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""Arrow-key selector and async wrapper used by model/skill picker dialogs.
|
|
2
|
+
|
|
3
|
+
from ui.picker import arrow_select, run_picker_in_thread
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from aria_code.ui.console import _HAS_TERMIOS, _esc_watcher
|
|
13
|
+
|
|
14
|
+
if _HAS_TERMIOS:
|
|
15
|
+
import termios
|
|
16
|
+
import tty
|
|
17
|
+
import select as _select
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def arrow_select(options: list, selected: int = 0, title: str = "",
|
|
21
|
+
max_visible: int = 10,
|
|
22
|
+
controls_hint: str = "↑↓ Enter Esc/q Cancel",
|
|
23
|
+
collapse_to: str | None = None,
|
|
24
|
+
shortcuts: dict | None = None,
|
|
25
|
+
numbered: bool = False) -> int:
|
|
26
|
+
"""Interactive arrow-key selector with scrolling.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
options: list of ``(label, description)`` tuples or plain strings
|
|
30
|
+
selected: initially highlighted index
|
|
31
|
+
title: optional header line
|
|
32
|
+
max_visible: max rows shown at once; scrolls when list is larger
|
|
33
|
+
collapse_to: when given, the menu is erased once answered and one
|
|
34
|
+
line is left in its place — "✓ Yes fx.py" — instead of
|
|
35
|
+
the whole menu, as Codex leaves an answered approval.
|
|
36
|
+
The text names what was being approved.
|
|
37
|
+
shortcuts: ``{"y": 0, "n": 3}`` — one key answers with that option
|
|
38
|
+
at once; the key is shown after its label, "(y)".
|
|
39
|
+
numbered: show "1." … before labels; digits 1–9 answer directly.
|
|
40
|
+
Returns:
|
|
41
|
+
index of chosen option, or -1 if cancelled
|
|
42
|
+
"""
|
|
43
|
+
if not options:
|
|
44
|
+
return -1
|
|
45
|
+
keys = {str(key): index for key, index in (shortcuts or {}).items()
|
|
46
|
+
if len(str(key)) == 1 and 0 <= index < len(options)}
|
|
47
|
+
key_of = {index: key for key, index in keys.items()}
|
|
48
|
+
|
|
49
|
+
def _label(index: int, label: str) -> str:
|
|
50
|
+
text = f"{index + 1}. {label}" if numbered else label
|
|
51
|
+
return f"{text} ({key_of[index]})" if index in key_of else text
|
|
52
|
+
|
|
53
|
+
if not _HAS_TERMIOS or not sys.stdin.isatty():
|
|
54
|
+
if title:
|
|
55
|
+
print(f"\n {title}\n")
|
|
56
|
+
for i, opt in enumerate(options):
|
|
57
|
+
label = opt[0] if isinstance(opt, tuple) else opt
|
|
58
|
+
marker = "❯" if i == selected else " "
|
|
59
|
+
print(f" {marker} {i + 1:2d}. {_label(i, label) if keys else label}")
|
|
60
|
+
try:
|
|
61
|
+
c = input("\n Enter number (or Enter to keep current): ").strip()
|
|
62
|
+
if not c:
|
|
63
|
+
return selected
|
|
64
|
+
if c in keys:
|
|
65
|
+
return keys[c]
|
|
66
|
+
idx = int(c) - 1
|
|
67
|
+
return idx if 0 <= idx < len(options) else -1
|
|
68
|
+
except (ValueError, EOFError, KeyboardInterrupt):
|
|
69
|
+
return -1
|
|
70
|
+
|
|
71
|
+
n = len(options)
|
|
72
|
+
visible = min(max_visible, n)
|
|
73
|
+
scroll = max(0, selected - visible + 1)
|
|
74
|
+
|
|
75
|
+
fd = sys.stdin.fileno()
|
|
76
|
+
old_settings = termios.tcgetattr(fd)
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
_tcols = os.get_terminal_size(fd).columns
|
|
80
|
+
except Exception:
|
|
81
|
+
_tcols = 80
|
|
82
|
+
|
|
83
|
+
_rule = "─" * min(_tcols, 72)
|
|
84
|
+
|
|
85
|
+
def _display_width(s: str) -> int:
|
|
86
|
+
import re as _re
|
|
87
|
+
clean = _re.sub(r'\x1b\[[0-9;]*[mJKHABCDfGrs]', '', s)
|
|
88
|
+
w = 0
|
|
89
|
+
for ch in clean:
|
|
90
|
+
cp = ord(ch)
|
|
91
|
+
if (0x1100 <= cp <= 0x115F or 0x2E80 <= cp <= 0xA4CF or
|
|
92
|
+
0xAC00 <= cp <= 0xD7AF or 0xF900 <= cp <= 0xFAFF or
|
|
93
|
+
0xFE10 <= cp <= 0xFE1F or 0xFE30 <= cp <= 0xFE4F or
|
|
94
|
+
0xFF01 <= cp <= 0xFF60 or 0xFFE0 <= cp <= 0xFFE6 or
|
|
95
|
+
0x3000 <= cp <= 0x303F):
|
|
96
|
+
w += 2
|
|
97
|
+
else:
|
|
98
|
+
w += 1
|
|
99
|
+
return w
|
|
100
|
+
|
|
101
|
+
def _physical_lines(text: str) -> int:
|
|
102
|
+
dw = _display_width(text)
|
|
103
|
+
return max(1, (dw + _tcols - 1) // _tcols)
|
|
104
|
+
|
|
105
|
+
def _raw(s: str):
|
|
106
|
+
os.write(1, s.encode())
|
|
107
|
+
|
|
108
|
+
def _render():
|
|
109
|
+
nonlocal scroll
|
|
110
|
+
if selected < scroll:
|
|
111
|
+
scroll = selected
|
|
112
|
+
elif selected >= scroll + visible:
|
|
113
|
+
scroll = selected - visible + 1
|
|
114
|
+
|
|
115
|
+
buf = ""
|
|
116
|
+
if _render.drawn:
|
|
117
|
+
buf += f"\033[{_render.last_phys_height}A"
|
|
118
|
+
|
|
119
|
+
phys_height = 0
|
|
120
|
+
for row in range(visible):
|
|
121
|
+
idx = scroll + row
|
|
122
|
+
opt = options[idx]
|
|
123
|
+
label = opt[0] if isinstance(opt, tuple) else opt
|
|
124
|
+
desc = opt[1] if isinstance(opt, tuple) and len(opt) > 1 else ""
|
|
125
|
+
if not label.strip().startswith("──"):
|
|
126
|
+
label = _label(idx, label)
|
|
127
|
+
if label.strip().startswith("──"):
|
|
128
|
+
line = f" \033[2m{label}\033[0m"
|
|
129
|
+
elif idx == selected:
|
|
130
|
+
_accent = os.getenv("ARIA_ACCENT_COLOR", "192;128;80")
|
|
131
|
+
line = f" \033[1m\033[38;2;{_accent}m❯\033[0m \033[1m{label}\033[0m"
|
|
132
|
+
if desc:
|
|
133
|
+
line += f" \033[2m{desc}\033[0m"
|
|
134
|
+
else:
|
|
135
|
+
line = f" {label}"
|
|
136
|
+
if desc:
|
|
137
|
+
line += f" \033[2m{desc}\033[0m"
|
|
138
|
+
buf += f"\033[2K{line}\n"
|
|
139
|
+
phys_height += _physical_lines(line)
|
|
140
|
+
|
|
141
|
+
if n > visible:
|
|
142
|
+
hint = f" \033[2m{selected + 1}/{n}\033[0m"
|
|
143
|
+
buf += f"\033[2K{hint}\n"
|
|
144
|
+
else:
|
|
145
|
+
buf += "\033[2K\n"
|
|
146
|
+
phys_height += 1
|
|
147
|
+
|
|
148
|
+
_render.last_phys_height = phys_height
|
|
149
|
+
_raw(buf)
|
|
150
|
+
_render.drawn = True
|
|
151
|
+
|
|
152
|
+
_render.drawn = False
|
|
153
|
+
_render.last_phys_height = visible + 1
|
|
154
|
+
header_text = f" {title} {controls_hint}" if title else f" {controls_hint}"
|
|
155
|
+
# blank line + rule, then the title/hint line(s) + blank line
|
|
156
|
+
header_height = 2 + _physical_lines(header_text) + 1
|
|
157
|
+
result = -1
|
|
158
|
+
|
|
159
|
+
def _choose() -> int:
|
|
160
|
+
nonlocal selected
|
|
161
|
+
while True:
|
|
162
|
+
ch = os.read(fd, 1)
|
|
163
|
+
if ch == b'\x1b':
|
|
164
|
+
seq = b''
|
|
165
|
+
if _select.select([fd], [], [], 0.05)[0]:
|
|
166
|
+
seq = os.read(fd, 2)
|
|
167
|
+
if seq == b'[A':
|
|
168
|
+
selected = (selected - 1) % n; _render()
|
|
169
|
+
elif seq == b'[B':
|
|
170
|
+
selected = (selected + 1) % n; _render()
|
|
171
|
+
elif seq == b'[5~':
|
|
172
|
+
selected = max(0, selected - visible); _render()
|
|
173
|
+
elif seq == b'[6~':
|
|
174
|
+
selected = min(n - 1, selected + visible); _render()
|
|
175
|
+
elif not seq:
|
|
176
|
+
return -1
|
|
177
|
+
elif ch in (b'\r', b'\n'):
|
|
178
|
+
return selected
|
|
179
|
+
elif ch.decode(errors="ignore") in keys:
|
|
180
|
+
selected = keys[ch.decode(errors="ignore")]
|
|
181
|
+
return selected
|
|
182
|
+
elif numbered and ch.isdigit() and 1 <= int(ch) <= n:
|
|
183
|
+
selected = int(ch) - 1
|
|
184
|
+
return selected
|
|
185
|
+
elif ch == b'q':
|
|
186
|
+
return -1
|
|
187
|
+
elif ch == b'k':
|
|
188
|
+
selected = (selected - 1) % n; _render()
|
|
189
|
+
elif ch == b'j':
|
|
190
|
+
selected = (selected + 1) % n; _render()
|
|
191
|
+
elif ch == b'g':
|
|
192
|
+
selected = 0; _render()
|
|
193
|
+
elif ch == b'G':
|
|
194
|
+
selected = n - 1; _render()
|
|
195
|
+
elif ch in (b'\x03', b'\x04'):
|
|
196
|
+
return -1
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
_esc_watcher.pause()
|
|
200
|
+
tty.setcbreak(fd)
|
|
201
|
+
sys.stdout.flush()
|
|
202
|
+
|
|
203
|
+
# Top boundary
|
|
204
|
+
_raw(f"\n \033[2m{_rule}\033[0m\n")
|
|
205
|
+
if title:
|
|
206
|
+
_raw(f" \033[1m{title}\033[0m \033[2m{controls_hint}\033[0m\n\n")
|
|
207
|
+
else:
|
|
208
|
+
_raw(f" \033[2m{controls_hint}\033[0m\n\n")
|
|
209
|
+
|
|
210
|
+
_render()
|
|
211
|
+
result = _choose()
|
|
212
|
+
return result
|
|
213
|
+
except (EOFError, KeyboardInterrupt, OSError):
|
|
214
|
+
return -1
|
|
215
|
+
finally:
|
|
216
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
|
217
|
+
_esc_watcher.resume()
|
|
218
|
+
if collapse_to is not None and _render.drawn:
|
|
219
|
+
label = ""
|
|
220
|
+
if 0 <= result < n:
|
|
221
|
+
opt = options[result]
|
|
222
|
+
label = opt[0] if isinstance(opt, tuple) else opt
|
|
223
|
+
declined = result < 0 or label.strip().lower().startswith(("no", "否", "拒绝", "取消", "cancel"))
|
|
224
|
+
mark = "\033[31m✗\033[0m" if declined else "\033[32m✓\033[0m"
|
|
225
|
+
shown = label or "Cancelled"
|
|
226
|
+
subject = f" \033[2m{collapse_to}\033[0m" if collapse_to else ""
|
|
227
|
+
# Up over the header and the menu, clear to the end, one line instead.
|
|
228
|
+
_raw(f"\033[{header_height + _render.last_phys_height}A\r\033[J {mark} {shown}{subject}\n")
|
|
229
|
+
else:
|
|
230
|
+
_raw(f" \033[2m{_rule}\033[0m\n\n")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
async def run_picker_in_thread(options: list, current_idx: int,
|
|
234
|
+
title: str, max_visible: int = 14,
|
|
235
|
+
controls_hint: str = "↑↓ Enter Esc/q Cancel") -> int:
|
|
236
|
+
"""Run arrow_select in an executor thread to avoid kqueue conflicts on macOS."""
|
|
237
|
+
loop = asyncio.get_running_loop()
|
|
238
|
+
return await loop.run_in_executor(
|
|
239
|
+
None,
|
|
240
|
+
lambda: arrow_select(
|
|
241
|
+
options, current_idx, title, max_visible, controls_hint
|
|
242
|
+
),
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# Back-compat aliases used by aria_cli.py
|
|
247
|
+
_arrow_select = arrow_select
|
|
248
|
+
_run_picker_in_thread = run_picker_in_thread
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""UI rendering helpers — team, finance, market output formatters."""
|
|
2
|
+
|
|
3
|
+
from .team import render_verdict_banner, render_team_table
|
|
4
|
+
from .finance import render_macro_result, render_cb_rates, render_econ_calendar
|
|
5
|
+
from .market import print_quote_result, print_ta_result
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"render_verdict_banner", "render_team_table",
|
|
9
|
+
"render_macro_result", "render_cb_rates", "render_econ_calendar",
|
|
10
|
+
"print_quote_result", "print_ta_result",
|
|
11
|
+
]
|