aria-code 0.52.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aria_code/__init__.py +42 -0
- aria_code/_version.py +20 -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 +34 -0
- aria_code/agents/base.py +318 -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 +303 -0
- aria_code/agents/financial/fundamental.py +191 -0
- aria_code/agents/financial/macro.py +99 -0
- aria_code/agents/financial/news.py +207 -0
- aria_code/agents/financial/risk.py +165 -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 +258 -0
- aria_code/agents/orchestrator.py +44 -0
- aria_code/agents/portfolio_agent.py +363 -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 +158 -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 +492 -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/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 +15 -0
- aria_code/apps/channels/__init__.py +17 -0
- aria_code/apps/channels/intake.py +92 -0
- aria_code/apps/channels/registry.py +95 -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/bootstrap.py +145 -0
- aria_code/apps/cli/broker_render.py +206 -0
- aria_code/apps/cli/codegen_paths.py +29 -0
- aria_code/apps/cli/commands/__init__.py +16 -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 +369 -0
- aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
- aria_code/apps/cli/commands/auth_cmds.py +239 -0
- aria_code/apps/cli/commands/backtest_cmds.py +2543 -0
- aria_code/apps/cli/commands/broker_cmds.py +1234 -0
- aria_code/apps/cli/commands/business_workflow_cmds.py +319 -0
- aria_code/apps/cli/commands/canvas_cmds.py +77 -0
- aria_code/apps/cli/commands/catalog.py +87 -0
- aria_code/apps/cli/commands/core_cmds.py +2520 -0
- aria_code/apps/cli/commands/data_cmds.py +457 -0
- aria_code/apps/cli/commands/diagnostic_cmds.py +230 -0
- aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -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 +434 -0
- aria_code/apps/cli/commands/market_cmds.py +1381 -0
- aria_code/apps/cli/commands/market_context.py +425 -0
- aria_code/apps/cli/commands/market_render.py +7 -0
- aria_code/apps/cli/commands/model_cmds.py +2153 -0
- aria_code/apps/cli/commands/ops_cmds.py +721 -0
- aria_code/apps/cli/commands/orchestrator_cmds.py +179 -0
- aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
- aria_code/apps/cli/commands/portfolio_cmds.py +1278 -0
- aria_code/apps/cli/commands/report.py +437 -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 +669 -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 +79 -0
- aria_code/apps/cli/commands/workflow_cmds.py +480 -0
- aria_code/apps/cli/commands/workspace_cmds.py +1494 -0
- aria_code/apps/cli/config_paths.py +73 -0
- aria_code/apps/cli/config_store.py +78 -0
- aria_code/apps/cli/constants.py +88 -0
- aria_code/apps/cli/context.py +34 -0
- aria_code/apps/cli/deterministic.py +191 -0
- aria_code/apps/cli/direct.py +48 -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 +196 -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 +1309 -0
- aria_code/apps/cli/handlers/market_handlers.py +2513 -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/helpers.py +302 -0
- aria_code/apps/cli/hooks.py +180 -0
- aria_code/apps/cli/i18n.py +297 -0
- aria_code/apps/cli/intent.py +136 -0
- aria_code/apps/cli/intent_router.py +276 -0
- aria_code/apps/cli/intent_signals.py +344 -0
- aria_code/apps/cli/lifecycle_hooks.py +48 -0
- aria_code/apps/cli/local_tool_schemas.py +536 -0
- aria_code/apps/cli/main.py +29 -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/model_catalog.py +620 -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 +59 -0
- aria_code/apps/cli/prompts/__init__.py +0 -0
- aria_code/apps/cli/prompts/coding.py +53 -0
- aria_code/apps/cli/prompts/select.py +142 -0
- aria_code/apps/cli/prompts/system_prompts.py +552 -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 +521 -0
- aria_code/apps/cli/providers/chat_routing.py +128 -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 +1594 -0
- aria_code/apps/cli/providers/llm/response_cache.py +60 -0
- aria_code/apps/cli/providers/llm/sse_stream.py +257 -0
- aria_code/apps/cli/providers/runtime_bridge.py +353 -0
- aria_code/apps/cli/providers/vertexai_stream.py +316 -0
- aria_code/apps/cli/runtime_consumer.py +657 -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_store.py +112 -0
- aria_code/apps/cli/skills_catalog.py +273 -0
- aria_code/apps/cli/todo_tracker.py +190 -0
- aria_code/apps/cli/tool_executor.py +823 -0
- aria_code/apps/cli/tool_registry.py +34 -0
- aria_code/apps/cli/tool_scope.py +106 -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 +180 -0
- aria_code/apps/cli/tools/market_tools.py +620 -0
- aria_code/apps/cli/tools/notebook_tools.py +111 -0
- aria_code/apps/cli/tools/system_tools.py +726 -0
- aria_code/apps/cli/tools/write_tools.py +845 -0
- aria_code/apps/cli/tradingview_bridge.py +529 -0
- aria_code/apps/cli/turn_planning.py +137 -0
- aria_code/apps/cli/update_check.py +153 -0
- aria_code/apps/cli/utils/__init__.py +0 -0
- aria_code/apps/cli/utils/market_detect.py +1597 -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 +6743 -0
- aria_code/aria_daemon.py +1398 -0
- aria_code/aria_feishu_bot.py +1423 -0
- aria_code/aria_mcp_server.py +7 -0
- aria_code/aria_relay_client.py +4 -0
- aria_code/aria_relay_server.py +490 -0
- aria_code/aria_telegram_bot.py +202 -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 +182 -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 +1976 -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 +181 -0
- aria_code/command_safety.py +19 -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/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/demo_player.py +207 -0
- aria_code/doctor.py +813 -0
- aria_code/domain/__init__.py +0 -0
- aria_code/domain/backtest_engine.py +354 -0
- aria_code/domain/backtest_report.py +472 -0
- aria_code/domain/finance_formulas.py +389 -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/harness.py +598 -0
- aria_code/evals/runner.py +238 -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 +386 -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 +639 -0
- aria_code/memory_manager.py +246 -0
- aria_code/model_capability.py +486 -0
- aria_code/notification_tools.py +4 -0
- aria_code/openai_image_client.py +4 -0
- aria_code/packages/__init__.py +23 -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 +52 -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 +201 -0
- aria_code/packages/aria_mcp/circuit.py +82 -0
- aria_code/packages/aria_mcp/config.py +111 -0
- aria_code/packages/aria_mcp/installer.py +95 -0
- aria_code/packages/aria_mcp/server.py +1550 -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 +396 -0
- aria_code/packages/aria_sdk/providers.py +70 -0
- aria_code/packages/aria_sdk/streaming.py +79 -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 +268 -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 +57 -0
- aria_code/packages/aria_services/research_quality.py +186 -0
- aria_code/packages/aria_services/settings.py +157 -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 +8 -0
- aria_code/packages/aria_tools/financial/_paths.py +130 -0
- aria_code/packages/aria_tools/financial/compliance.py +31 -0
- aria_code/packages/aria_tools/financial/factors.py +33 -0
- aria_code/packages/aria_tools/financial/risk_tools.py +33 -0
- aria_code/packages/aria_tools/financial/strategy.py +31 -0
- aria_code/packages/aria_tools/registry.py +128 -0
- aria_code/packages/quant_engine/__init__.py +34 -0
- aria_code/packages/quant_engine/_namespace.py +62 -0
- aria_code/packages/quant_engine/backtest/__init__.py +14 -0
- aria_code/packages/quant_engine/backtest/core.py +53 -0
- aria_code/packages/quant_engine/backtest/engine.py +96 -0
- aria_code/packages/quant_engine/portfolio/__init__.py +13 -0
- aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
- aria_code/packages/quant_engine/sports/__init__.py +80 -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/ml_model.py +377 -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 +35 -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/logistics/__init__.py +169 -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/llm/__init__.py +19 -0
- aria_code/providers/llm/anthropic.py +184 -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 +129 -0
- aria_code/providers/llm/openai_compat.py +313 -0
- aria_code/providers/llm/registry.py +444 -0
- aria_code/providers/local_image_provider.py +202 -0
- aria_code/providers/local_llm_provider.py +589 -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/runtime/__init__.py +169 -0
- aria_code/runtime/acceptance.py +481 -0
- aria_code/runtime/agent_loop.py +1520 -0
- aria_code/runtime/approval.py +57 -0
- aria_code/runtime/budget.py +232 -0
- aria_code/runtime/checkpoints.py +432 -0
- aria_code/runtime/crash_report.py +174 -0
- aria_code/runtime/events.py +113 -0
- aria_code/runtime/gateway.py +150 -0
- aria_code/runtime/lsp.py +484 -0
- aria_code/runtime/orchestrator.py +55 -0
- aria_code/runtime/repo_map.py +700 -0
- aria_code/runtime/run_state.py +127 -0
- aria_code/runtime/run_store.py +450 -0
- aria_code/runtime/self_healing.py +422 -0
- aria_code/runtime/subagent.py +547 -0
- aria_code/runtime/task_ledger.py +86 -0
- aria_code/runtime/task_orchestrator.py +90 -0
- aria_code/runtime/tool_executor.py +217 -0
- aria_code/runtime/tool_policy.py +107 -0
- aria_code/runtime/worktrees.py +215 -0
- aria_code/runway_video_client.py +4 -0
- aria_code/safety/__init__.py +23 -0
- aria_code/safety/permissions.py +306 -0
- aria_code/safety/service.py +102 -0
- aria_code/setup_wizard.py +673 -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 +504 -0
- aria_code/tools/data_analysis_tools.py +809 -0
- aria_code/tools/enterprise_finance_tools.py +156 -0
- aria_code/tools/extended_tools.py +240 -0
- aria_code/tools/file_analysis_tools.py +885 -0
- aria_code/tools/image_gen_tools.py +114 -0
- aria_code/tools/local_finance_tools.py +3417 -0
- aria_code/tools/logistics_tools.py +135 -0
- aria_code/tools/macro_tools.py +369 -0
- aria_code/tools/notification_tools.py +249 -0
- aria_code/tools/project_tools.py +525 -0
- aria_code/tools/realty_data_tools.py +659 -0
- aria_code/tools/spreadsheet_tools.py +388 -0
- aria_code/tools/stripe_tools.py +115 -0
- aria_code/ui/__init__.py +105 -0
- aria_code/ui/banner.py +508 -0
- aria_code/ui/completer.py +501 -0
- aria_code/ui/console.py +281 -0
- aria_code/ui/image_render.py +243 -0
- aria_code/ui/input_box.py +488 -0
- aria_code/ui/picker.py +201 -0
- aria_code/ui/render/__init__.py +11 -0
- aria_code/ui/render/finance.py +1705 -0
- aria_code/ui/render/market.py +225 -0
- aria_code/ui/render/output.py +775 -0
- aria_code/ui/render/responsive.py +75 -0
- aria_code/ui/render/team.py +354 -0
- aria_code/ui/robot.py +235 -0
- aria_code/ui/startup_dashboard.py +109 -0
- aria_code/utils/vscode_uri.py +37 -0
- aria_code/video_analysis.py +147 -0
- aria_code/video_editor.py +271 -0
- aria_code/workspace/__init__.py +6 -0
- aria_code/workspace/files.py +193 -0
- aria_code/workspace/verify.py +113 -0
- aria_code/workspace_changes.py +199 -0
- aria_code/workspace_context.py +233 -0
- aria_code/workspace_service.py +196 -0
- aria_code/workspace_tools.py +150 -0
- aria_code-0.52.0.dist-info/METADATA +237 -0
- aria_code-0.52.0.dist-info/RECORD +478 -0
- aria_code-0.52.0.dist-info/WHEEL +5 -0
- aria_code-0.52.0.dist-info/entry_points.txt +3 -0
- aria_code-0.52.0.dist-info/licenses/LICENSE +201 -0
- aria_code-0.52.0.dist-info/licenses/NOTICE +49 -0
- aria_code-0.52.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
"""Prompt-toolkit input panel — lightweight Claude Code-style input block.
|
|
2
|
+
|
|
3
|
+
Layout:
|
|
4
|
+
────────────────────────────────────────────── ← subtle top rule
|
|
5
|
+
› cursor_ ← padded input row
|
|
6
|
+
────────────────────────────────────────────── ← subtle bottom rule
|
|
7
|
+
model · ~/workspace ← dim status bar
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import os
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
16
|
+
import sys
|
|
17
|
+
import time
|
|
18
|
+
from contextlib import contextmanager
|
|
19
|
+
from dataclasses import dataclass, replace
|
|
20
|
+
from typing import Callable, Optional
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from prompt_toolkit.application import Application
|
|
24
|
+
from prompt_toolkit.buffer import Buffer
|
|
25
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
26
|
+
from prompt_toolkit.layout.dimension import Dimension
|
|
27
|
+
from prompt_toolkit.layout import Float, FloatContainer, HSplit, Layout, VSplit, Window
|
|
28
|
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
|
29
|
+
from prompt_toolkit.layout.menus import CompletionsMenu
|
|
30
|
+
from prompt_toolkit.layout.processors import Processor, Transformation
|
|
31
|
+
from prompt_toolkit.styles import Style
|
|
32
|
+
from prompt_toolkit.widgets import TextArea
|
|
33
|
+
HAS_PROMPT_TOOLKIT = True
|
|
34
|
+
except ImportError:
|
|
35
|
+
HAS_PROMPT_TOOLKIT = False
|
|
36
|
+
|
|
37
|
+
class Processor: # type: ignore[no-redef]
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
class Transformation: # type: ignore[no-redef]
|
|
41
|
+
def __init__(self, fragments, source_to_display=None, display_to_source=None):
|
|
42
|
+
self.fragments = fragments
|
|
43
|
+
self.source_to_display = source_to_display or (lambda i: i)
|
|
44
|
+
self.display_to_source = display_to_source or (lambda i: i)
|
|
45
|
+
|
|
46
|
+
class Style: # type: ignore[no-redef]
|
|
47
|
+
@staticmethod
|
|
48
|
+
def from_dict(values):
|
|
49
|
+
return values
|
|
50
|
+
|
|
51
|
+
Application = Buffer = KeyBindings = Dimension = None # type: ignore
|
|
52
|
+
Float = FloatContainer = HSplit = Layout = VSplit = Window = None # type: ignore
|
|
53
|
+
FormattedTextControl = CompletionsMenu = TextArea = None # type: ignore
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ── Theme detection ────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
def detect_terminal_theme() -> str:
|
|
59
|
+
explicit = os.getenv("ARIA_INPUT_THEME", "").strip().lower()
|
|
60
|
+
if explicit in {"dark", "light"}:
|
|
61
|
+
return explicit
|
|
62
|
+
colorfgbg = os.getenv("COLORFGBG", "")
|
|
63
|
+
if colorfgbg:
|
|
64
|
+
try:
|
|
65
|
+
return "dark" if int(colorfgbg.split(";")[-1]) < 8 else "light"
|
|
66
|
+
except ValueError:
|
|
67
|
+
pass
|
|
68
|
+
if os.getenv("TERM_PROGRAM", "") == "Apple_Terminal":
|
|
69
|
+
return "light"
|
|
70
|
+
# os.uname() is Unix-only — doesn't exist on Windows at all.
|
|
71
|
+
if sys.platform == "darwin":
|
|
72
|
+
try:
|
|
73
|
+
r = subprocess.run(
|
|
74
|
+
["defaults", "read", "-g", "AppleInterfaceStyle"],
|
|
75
|
+
capture_output=True, text=True, timeout=0.2, check=False,
|
|
76
|
+
)
|
|
77
|
+
return "dark" if (r.returncode == 0 and "dark" in r.stdout.lower()) else "light"
|
|
78
|
+
except Exception:
|
|
79
|
+
pass
|
|
80
|
+
return "dark"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ── Config ─────────────────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
@dataclass
|
|
86
|
+
class PanelInputConfig:
|
|
87
|
+
prompt: str = "› "
|
|
88
|
+
placeholder: str = ""
|
|
89
|
+
theme: str = "auto"
|
|
90
|
+
lang: str = "en"
|
|
91
|
+
|
|
92
|
+
est_tokens: int = 0
|
|
93
|
+
max_tokens: int = 131072
|
|
94
|
+
|
|
95
|
+
# Status bar display
|
|
96
|
+
model_label: str = ""
|
|
97
|
+
cwd: str = ""
|
|
98
|
+
|
|
99
|
+
# Robot mascot — show animated dot in status bar
|
|
100
|
+
show_robot: bool = True
|
|
101
|
+
|
|
102
|
+
# Legacy fields kept for call-site compatibility
|
|
103
|
+
privacy: str = "local-only"
|
|
104
|
+
tools_count: int = 0
|
|
105
|
+
skills_count: int = 0
|
|
106
|
+
ollama_status: str = ""
|
|
107
|
+
pending_file: str = ""
|
|
108
|
+
permission_mode: str = "workspace-write"
|
|
109
|
+
git_branch: str = ""
|
|
110
|
+
git_dirty: bool = False
|
|
111
|
+
mcp_running: int = 0
|
|
112
|
+
mcp_total: int = 0
|
|
113
|
+
mcp_tool_count: int = 0
|
|
114
|
+
|
|
115
|
+
# Resolved by .resolved()
|
|
116
|
+
fg: str = ""
|
|
117
|
+
accent: str = ""
|
|
118
|
+
accent_y: str = ""
|
|
119
|
+
accent_b: str = ""
|
|
120
|
+
muted: str = ""
|
|
121
|
+
dim: str = ""
|
|
122
|
+
sep: str = ""
|
|
123
|
+
input_bg: str = "" # intentional input-area background
|
|
124
|
+
ph_color: str = "" # very dim placeholder
|
|
125
|
+
box: str = "" # rounded border color
|
|
126
|
+
|
|
127
|
+
# Completion menu palette (copper, theme-aware)
|
|
128
|
+
menu_bg: str = ""
|
|
129
|
+
menu_fg: str = ""
|
|
130
|
+
menu_sel_bg: str = ""
|
|
131
|
+
menu_sel_fg: str = ""
|
|
132
|
+
menu_meta: str = ""
|
|
133
|
+
menu_meta_cur: str = ""
|
|
134
|
+
scroll_bg: str = ""
|
|
135
|
+
scroll_btn: str = ""
|
|
136
|
+
hi: str = "" # fuzzy-match highlight (copper)
|
|
137
|
+
|
|
138
|
+
def resolved(self) -> "PanelInputConfig":
|
|
139
|
+
theme = self.theme if self.theme != "auto" else detect_terminal_theme()
|
|
140
|
+
is_zh = self.lang.lower().startswith("zh")
|
|
141
|
+
placeholder = self.placeholder or (
|
|
142
|
+
"问 Aria、编辑文件或运行命令… / 命令 @ 上下文 ! shell"
|
|
143
|
+
if is_zh
|
|
144
|
+
else "Ask Aria, edit files, or run commands… / commands @ context ! shell"
|
|
145
|
+
)
|
|
146
|
+
if theme == "dark":
|
|
147
|
+
return replace(self, theme=theme, placeholder=placeholder,
|
|
148
|
+
fg="#ffffff",
|
|
149
|
+
accent="#3fb950", accent_y="#d29922", accent_b="#79c0ff",
|
|
150
|
+
muted="#6e7781", dim="#484f58", sep="#2d333b",
|
|
151
|
+
input_bg="default", # transparent — box border defines the zone
|
|
152
|
+
ph_color="#6e7781", # secondary text, readable on dark terminals
|
|
153
|
+
box="#C08050", # copper — Aria's brand accent on the frame
|
|
154
|
+
menu_bg="#161b22", menu_fg="#c9d1d9",
|
|
155
|
+
menu_sel_bg="#3a2e20", menu_sel_fg="#e8c9a6",
|
|
156
|
+
menu_meta="#6e7681", menu_meta_cur="#c0a585",
|
|
157
|
+
scroll_bg="#161b22", scroll_btn="#C08050",
|
|
158
|
+
hi="#C08050",
|
|
159
|
+
)
|
|
160
|
+
return replace(self, theme="light", placeholder=placeholder,
|
|
161
|
+
fg="#24292f",
|
|
162
|
+
accent="#1a7f37", accent_y="#9a6700", accent_b="#0969da",
|
|
163
|
+
muted="#57606a", dim="#8c959f", sep="#d0d7de",
|
|
164
|
+
input_bg="default",
|
|
165
|
+
ph_color="#6e7781",
|
|
166
|
+
box="#9a6700",
|
|
167
|
+
menu_bg="#f2eee4", menu_fg="#24292f",
|
|
168
|
+
menu_sel_bg="#e7e1d3", menu_sel_fg="#8a5a00",
|
|
169
|
+
menu_meta="#6e7781", menu_meta_cur="#8a5a00",
|
|
170
|
+
scroll_bg="#e7e1d3", scroll_btn="#9a6700",
|
|
171
|
+
hi="#9a6700",
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ── Processor (mode badge + placeholder) ──────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
class PromptAndPlaceholderProcessor(Processor):
|
|
178
|
+
def __init__(self, get_prefix: Callable[[], list], placeholder: str,
|
|
179
|
+
is_empty: Callable[[], bool]) -> None:
|
|
180
|
+
self.get_prefix = get_prefix
|
|
181
|
+
self.placeholder = placeholder
|
|
182
|
+
self.is_empty = is_empty
|
|
183
|
+
|
|
184
|
+
def apply_transformation(self, ti) -> Transformation:
|
|
185
|
+
if ti.lineno == 0:
|
|
186
|
+
empty = self.is_empty()
|
|
187
|
+
prefix = self.get_prefix()
|
|
188
|
+
pw = sum(len(t) for _, t in prefix)
|
|
189
|
+
frags = list(prefix)
|
|
190
|
+
if empty:
|
|
191
|
+
frags.append(("class:ph", self.placeholder))
|
|
192
|
+
frags.extend(ti.fragments)
|
|
193
|
+
return Transformation(
|
|
194
|
+
frags,
|
|
195
|
+
source_to_display=lambda i: pw + i,
|
|
196
|
+
display_to_source=lambda i: 0 if (i <= pw or empty) else max(0, i - pw),
|
|
197
|
+
)
|
|
198
|
+
return Transformation(ti.fragments)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
PlaceholderProcessor = PromptAndPlaceholderProcessor
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
INPUT_MAX_HEIGHT = 6
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# ── Style ──────────────────────────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
def _build_style(cfg: PanelInputConfig) -> Style:
|
|
210
|
+
return Style.from_dict({
|
|
211
|
+
# Input row: transparent bg — the rounded box border defines the zone
|
|
212
|
+
"input-bg": cfg.fg if cfg.input_bg == "default" else f"{cfg.fg} bg:{cfg.input_bg}",
|
|
213
|
+
"ph": cfg.ph_color,
|
|
214
|
+
# Rounded box border (Claude Code style)
|
|
215
|
+
"box": cfg.box,
|
|
216
|
+
# Mode prompt glyph — always copper (brand). 5-color discipline:
|
|
217
|
+
# red/green are reserved for 涨跌 semantics, never for chrome.
|
|
218
|
+
"mode-chat": f"bold {cfg.box}",
|
|
219
|
+
"mode-cmd": f"bold {cfg.box}",
|
|
220
|
+
"mode-file": f"bold {cfg.box}",
|
|
221
|
+
"prompt": cfg.muted,
|
|
222
|
+
# Divider (transparent bg — terminal bg shows through)
|
|
223
|
+
"divider": cfg.sep,
|
|
224
|
+
# Status bar (transparent bg)
|
|
225
|
+
"st-model": cfg.muted,
|
|
226
|
+
"st-sep": cfg.dim,
|
|
227
|
+
"st-cwd": cfg.dim,
|
|
228
|
+
"tok-warn": cfg.box, # copper — context-pressure caution
|
|
229
|
+
"tok-crit": "#f85149", # red — critical only
|
|
230
|
+
# Completion menu — theme-aware copper palette (matches terminal theme)
|
|
231
|
+
"completion-menu": f"bg:{cfg.menu_bg} {cfg.menu_fg}",
|
|
232
|
+
"completion-menu.completion": f"bg:{cfg.menu_bg} {cfg.menu_fg}",
|
|
233
|
+
"completion-menu.completion.current": f"bg:{cfg.menu_sel_bg} {cfg.menu_sel_fg} bold",
|
|
234
|
+
"completion-menu.meta.completion": f"bg:{cfg.menu_bg} {cfg.menu_meta}",
|
|
235
|
+
"completion-menu.meta.completion.current": f"bg:{cfg.menu_sel_bg} {cfg.menu_meta_cur}",
|
|
236
|
+
"completion-menu.multi-column-meta": f"bg:{cfg.menu_bg} {cfg.menu_meta}",
|
|
237
|
+
"scrollbar.background": f"bg:{cfg.scroll_bg}",
|
|
238
|
+
"scrollbar.button": f"bg:{cfg.scroll_btn}",
|
|
239
|
+
# Fuzzy-match highlight classes (shared with ui/completer.py) — copper
|
|
240
|
+
"fz-hi": f"bold {cfg.hi}",
|
|
241
|
+
"fz-cat": cfg.dim,
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# ── Row builders ───────────────────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
def _input_rule(cfg: PanelInputConfig) -> list:
|
|
248
|
+
w = shutil.get_terminal_size((80, 24)).columns
|
|
249
|
+
return [("class:divider", "─" * w)]
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _input_pad() -> list:
|
|
253
|
+
return [("", " ")]
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _mode_prefix(cfg: PanelInputConfig, text_getter: Callable[[], str]) -> list:
|
|
257
|
+
"""Claude Code-style › glyph — color shifts by detected input mode."""
|
|
258
|
+
txt = text_getter().lstrip()
|
|
259
|
+
if txt.startswith("/"):
|
|
260
|
+
return [("class:mode-cmd", "› ")]
|
|
261
|
+
if txt.startswith("@") or txt.startswith("!"):
|
|
262
|
+
return [("class:mode-file", "› ")]
|
|
263
|
+
return [("class:mode-chat", "› ")]
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _status_bar(cfg: PanelInputConfig) -> list:
|
|
267
|
+
"""Compact runtime row: model · workspace · MCP · permissions · context."""
|
|
268
|
+
from .robot import get_status_dot
|
|
269
|
+
|
|
270
|
+
tick = int(time.monotonic() * 4) # 4 fps tick without a background thread
|
|
271
|
+
parts: list = []
|
|
272
|
+
|
|
273
|
+
if cfg.show_robot:
|
|
274
|
+
dot_frags = get_status_dot(tick)
|
|
275
|
+
parts.extend(dot_frags)
|
|
276
|
+
parts.append(("class:st-sep", " "))
|
|
277
|
+
|
|
278
|
+
width = shutil.get_terminal_size((80, 24)).columns
|
|
279
|
+
model_label = cfg.model_label
|
|
280
|
+
model_limit = 24 if width >= 90 else 19
|
|
281
|
+
if len(model_label) > model_limit:
|
|
282
|
+
model_label = model_label[: model_limit - 1] + "…"
|
|
283
|
+
if model_label:
|
|
284
|
+
parts.append(("class:st-model", model_label))
|
|
285
|
+
|
|
286
|
+
workspace = cfg.git_branch or os.path.basename(cfg.cwd.rstrip(os.sep))
|
|
287
|
+
if workspace:
|
|
288
|
+
if model_label:
|
|
289
|
+
parts.append(("class:st-sep", " · "))
|
|
290
|
+
if cfg.git_branch and cfg.git_dirty:
|
|
291
|
+
workspace += "*"
|
|
292
|
+
parts.append(("class:st-cwd", workspace))
|
|
293
|
+
|
|
294
|
+
if cfg.mcp_total:
|
|
295
|
+
mcp_label = (
|
|
296
|
+
f"MCP {cfg.mcp_tool_count}"
|
|
297
|
+
if cfg.mcp_running == cfg.mcp_total and cfg.mcp_tool_count
|
|
298
|
+
else f"MCP {cfg.mcp_running}/{cfg.mcp_total}"
|
|
299
|
+
)
|
|
300
|
+
parts += [("class:st-sep", " · "), ("class:st-cwd", mcp_label)]
|
|
301
|
+
|
|
302
|
+
is_zh = cfg.lang.lower().startswith("zh")
|
|
303
|
+
permission_labels = {
|
|
304
|
+
"read-only": "只读" if is_zh else "ro",
|
|
305
|
+
"workspace-write": "可写" if is_zh else "rw",
|
|
306
|
+
"full-access": "完整权限" if is_zh else "full",
|
|
307
|
+
}
|
|
308
|
+
permission = permission_labels.get(cfg.permission_mode, cfg.permission_mode)
|
|
309
|
+
if permission:
|
|
310
|
+
parts += [("class:st-sep", " · "), ("class:st-cwd", permission)]
|
|
311
|
+
|
|
312
|
+
ratio = cfg.est_tokens / max(cfg.max_tokens, 1)
|
|
313
|
+
tc = "tok-crit" if ratio >= 0.85 else ("tok-warn" if ratio >= 0.60 else "st-cwd")
|
|
314
|
+
# ratio<1% 一律显示 "<1%"(含估算为 0 的首帧)——"ctx 0%" 是误导:
|
|
315
|
+
# 系统提示/skills 一定占用了上下文,只是估算看不见。
|
|
316
|
+
context_prefix = "上下文" if is_zh else "ctx "
|
|
317
|
+
context_label = (
|
|
318
|
+
f"{context_prefix}<1%" if ratio < 0.01
|
|
319
|
+
else f"{context_prefix}{ratio:.0%}"
|
|
320
|
+
)
|
|
321
|
+
parts += [("class:st-sep", " · "), (f"class:{tc}", context_label)]
|
|
322
|
+
|
|
323
|
+
shortcuts = (
|
|
324
|
+
"? 快捷键 · / 命令 · @ 上下文 · ! shell"
|
|
325
|
+
if cfg.lang.lower().startswith("zh")
|
|
326
|
+
else "? shortcuts · / commands · @ context · ! shell"
|
|
327
|
+
)
|
|
328
|
+
used = sum(len(text) for _, text in parts)
|
|
329
|
+
if width >= 110 and used + len(shortcuts) + 4 <= width:
|
|
330
|
+
parts += [("class:st-sep", " "), ("class:st-cwd", shortcuts)]
|
|
331
|
+
|
|
332
|
+
return parts
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# ── Main ───────────────────────────────────────────────────────────────────────
|
|
336
|
+
|
|
337
|
+
def _build_panel_input_application(
|
|
338
|
+
*,
|
|
339
|
+
completer=None,
|
|
340
|
+
history=None,
|
|
341
|
+
status_text: Callable[[], str] | str = "", # kept for compat
|
|
342
|
+
config: Optional[PanelInputConfig] = None,
|
|
343
|
+
) -> Optional[Application]:
|
|
344
|
+
cfg = (config or PanelInputConfig()).resolved()
|
|
345
|
+
if not HAS_PROMPT_TOOLKIT:
|
|
346
|
+
return None
|
|
347
|
+
|
|
348
|
+
def _accept(buf: Buffer) -> bool:
|
|
349
|
+
app.exit(result=buf.text)
|
|
350
|
+
return True
|
|
351
|
+
|
|
352
|
+
def _get_text() -> str:
|
|
353
|
+
try:
|
|
354
|
+
return text_area.text
|
|
355
|
+
except Exception:
|
|
356
|
+
return ""
|
|
357
|
+
|
|
358
|
+
text_area = TextArea(
|
|
359
|
+
height=Dimension(min=1, max=INPUT_MAX_HEIGHT),
|
|
360
|
+
multiline=True,
|
|
361
|
+
wrap_lines=True,
|
|
362
|
+
dont_extend_height=True,
|
|
363
|
+
completer=completer,
|
|
364
|
+
complete_while_typing=True,
|
|
365
|
+
history=history,
|
|
366
|
+
prompt="",
|
|
367
|
+
input_processors=[
|
|
368
|
+
PromptAndPlaceholderProcessor(
|
|
369
|
+
lambda: _mode_prefix(cfg, _get_text),
|
|
370
|
+
cfg.placeholder,
|
|
371
|
+
lambda: _get_text() == "",
|
|
372
|
+
),
|
|
373
|
+
],
|
|
374
|
+
accept_handler=_accept,
|
|
375
|
+
style="class:input-bg", # only the input row gets the subtle bg
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
kb = KeyBindings()
|
|
379
|
+
|
|
380
|
+
@kb.add("escape")
|
|
381
|
+
def _cancel(event) -> None:
|
|
382
|
+
event.app.exit(result="")
|
|
383
|
+
|
|
384
|
+
@kb.add("enter", eager=True)
|
|
385
|
+
def _submit(event) -> None:
|
|
386
|
+
event.app.exit(result=text_area.text)
|
|
387
|
+
|
|
388
|
+
@kb.add("s-tab")
|
|
389
|
+
def _shift_tab(event) -> None:
|
|
390
|
+
event.app.current_buffer.complete_previous()
|
|
391
|
+
|
|
392
|
+
root = FloatContainer(
|
|
393
|
+
content=HSplit([
|
|
394
|
+
# Lightweight terminal-native input section.
|
|
395
|
+
Window(height=1,
|
|
396
|
+
content=FormattedTextControl(lambda: _input_rule(cfg), focusable=False)),
|
|
397
|
+
VSplit([
|
|
398
|
+
Window(width=1, content=FormattedTextControl(_input_pad, focusable=False)),
|
|
399
|
+
text_area,
|
|
400
|
+
Window(width=1, content=FormattedTextControl(_input_pad, focusable=False)),
|
|
401
|
+
]),
|
|
402
|
+
Window(height=1,
|
|
403
|
+
content=FormattedTextControl(lambda: _input_rule(cfg), focusable=False)),
|
|
404
|
+
# Status bar: transparent bg, dim model · cwd
|
|
405
|
+
Window(height=1,
|
|
406
|
+
content=FormattedTextControl(lambda: _status_bar(cfg), focusable=False)),
|
|
407
|
+
]),
|
|
408
|
+
floats=[
|
|
409
|
+
Float(
|
|
410
|
+
xcursor=True,
|
|
411
|
+
ycursor=True,
|
|
412
|
+
content=CompletionsMenu(max_height=12, scroll_offset=2),
|
|
413
|
+
)
|
|
414
|
+
],
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
app: Application = Application(
|
|
418
|
+
layout=Layout(root, focused_element=text_area),
|
|
419
|
+
key_bindings=kb,
|
|
420
|
+
style=_build_style(cfg),
|
|
421
|
+
full_screen=False,
|
|
422
|
+
erase_when_done=False,
|
|
423
|
+
mouse_support=False,
|
|
424
|
+
refresh_interval=0.25, # drives robot dot animation at 4 fps
|
|
425
|
+
)
|
|
426
|
+
return app
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
@contextmanager
|
|
430
|
+
def _without_cpr_probe():
|
|
431
|
+
"""Disable CPR for this inline panel, which owns a fixed-height layout."""
|
|
432
|
+
key = "PROMPT_TOOLKIT_NO_CPR"
|
|
433
|
+
previous = os.environ.get(key)
|
|
434
|
+
os.environ[key] = "1"
|
|
435
|
+
try:
|
|
436
|
+
yield
|
|
437
|
+
finally:
|
|
438
|
+
if previous is None:
|
|
439
|
+
os.environ.pop(key, None)
|
|
440
|
+
else:
|
|
441
|
+
os.environ[key] = previous
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def run_panel_input(
|
|
445
|
+
*,
|
|
446
|
+
completer=None,
|
|
447
|
+
history=None,
|
|
448
|
+
status_text: Callable[[], str] | str = "",
|
|
449
|
+
config: Optional[PanelInputConfig] = None,
|
|
450
|
+
) -> str:
|
|
451
|
+
"""Run the panel synchronously for compatibility with non-async callers."""
|
|
452
|
+
app = _build_panel_input_application(
|
|
453
|
+
completer=completer,
|
|
454
|
+
history=history,
|
|
455
|
+
status_text=status_text,
|
|
456
|
+
config=config,
|
|
457
|
+
)
|
|
458
|
+
if app is None:
|
|
459
|
+
try:
|
|
460
|
+
return input((config or PanelInputConfig()).prompt)
|
|
461
|
+
except EOFError:
|
|
462
|
+
return ""
|
|
463
|
+
with _without_cpr_probe():
|
|
464
|
+
return app.run() or ""
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
async def run_panel_input_async(
|
|
468
|
+
*,
|
|
469
|
+
completer=None,
|
|
470
|
+
history=None,
|
|
471
|
+
status_text: Callable[[], str] | str = "",
|
|
472
|
+
config: Optional[PanelInputConfig] = None,
|
|
473
|
+
) -> str:
|
|
474
|
+
"""Run the panel on the active event loop to preserve IME input state."""
|
|
475
|
+
app = _build_panel_input_application(
|
|
476
|
+
completer=completer,
|
|
477
|
+
history=history,
|
|
478
|
+
status_text=status_text,
|
|
479
|
+
config=config,
|
|
480
|
+
)
|
|
481
|
+
if app is None:
|
|
482
|
+
loop = asyncio.get_running_loop()
|
|
483
|
+
try:
|
|
484
|
+
return await loop.run_in_executor(None, input, (config or PanelInputConfig()).prompt)
|
|
485
|
+
except EOFError:
|
|
486
|
+
return ""
|
|
487
|
+
with _without_cpr_probe():
|
|
488
|
+
return (await app.run_async()) or ""
|
aria_code/ui/picker.py
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
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") -> int:
|
|
23
|
+
"""Interactive arrow-key selector with scrolling.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
options: list of ``(label, description)`` tuples or plain strings
|
|
27
|
+
selected: initially highlighted index
|
|
28
|
+
title: optional header line
|
|
29
|
+
max_visible: max rows shown at once; scrolls when list is larger
|
|
30
|
+
Returns:
|
|
31
|
+
index of chosen option, or -1 if cancelled
|
|
32
|
+
"""
|
|
33
|
+
if not options:
|
|
34
|
+
return -1
|
|
35
|
+
|
|
36
|
+
if not _HAS_TERMIOS or not sys.stdin.isatty():
|
|
37
|
+
if title:
|
|
38
|
+
print(f"\n {title}\n")
|
|
39
|
+
for i, opt in enumerate(options):
|
|
40
|
+
label = opt[0] if isinstance(opt, tuple) else opt
|
|
41
|
+
marker = "❯" if i == selected else " "
|
|
42
|
+
print(f" {marker} {i + 1:2d}. {label}")
|
|
43
|
+
try:
|
|
44
|
+
c = input("\n Enter number (or Enter to keep current): ").strip()
|
|
45
|
+
if not c:
|
|
46
|
+
return selected
|
|
47
|
+
idx = int(c) - 1
|
|
48
|
+
return idx if 0 <= idx < len(options) else -1
|
|
49
|
+
except (ValueError, EOFError, KeyboardInterrupt):
|
|
50
|
+
return -1
|
|
51
|
+
|
|
52
|
+
n = len(options)
|
|
53
|
+
visible = min(max_visible, n)
|
|
54
|
+
scroll = max(0, selected - visible + 1)
|
|
55
|
+
|
|
56
|
+
fd = sys.stdin.fileno()
|
|
57
|
+
old_settings = termios.tcgetattr(fd)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
_tcols = os.get_terminal_size(fd).columns
|
|
61
|
+
except Exception:
|
|
62
|
+
_tcols = 80
|
|
63
|
+
|
|
64
|
+
_rule = "─" * min(_tcols, 72)
|
|
65
|
+
|
|
66
|
+
def _display_width(s: str) -> int:
|
|
67
|
+
import re as _re
|
|
68
|
+
clean = _re.sub(r'\x1b\[[0-9;]*[mJKHABCDfGrs]', '', s)
|
|
69
|
+
w = 0
|
|
70
|
+
for ch in clean:
|
|
71
|
+
cp = ord(ch)
|
|
72
|
+
if (0x1100 <= cp <= 0x115F or 0x2E80 <= cp <= 0xA4CF or
|
|
73
|
+
0xAC00 <= cp <= 0xD7AF or 0xF900 <= cp <= 0xFAFF or
|
|
74
|
+
0xFE10 <= cp <= 0xFE1F or 0xFE30 <= cp <= 0xFE4F or
|
|
75
|
+
0xFF01 <= cp <= 0xFF60 or 0xFFE0 <= cp <= 0xFFE6 or
|
|
76
|
+
0x3000 <= cp <= 0x303F):
|
|
77
|
+
w += 2
|
|
78
|
+
else:
|
|
79
|
+
w += 1
|
|
80
|
+
return w
|
|
81
|
+
|
|
82
|
+
def _physical_lines(text: str) -> int:
|
|
83
|
+
dw = _display_width(text)
|
|
84
|
+
return max(1, (dw + _tcols - 1) // _tcols)
|
|
85
|
+
|
|
86
|
+
def _raw(s: str):
|
|
87
|
+
os.write(1, s.encode())
|
|
88
|
+
|
|
89
|
+
def _render():
|
|
90
|
+
nonlocal scroll
|
|
91
|
+
if selected < scroll:
|
|
92
|
+
scroll = selected
|
|
93
|
+
elif selected >= scroll + visible:
|
|
94
|
+
scroll = selected - visible + 1
|
|
95
|
+
|
|
96
|
+
buf = ""
|
|
97
|
+
if _render.drawn:
|
|
98
|
+
buf += f"\033[{_render.last_phys_height}A"
|
|
99
|
+
|
|
100
|
+
phys_height = 0
|
|
101
|
+
for row in range(visible):
|
|
102
|
+
idx = scroll + row
|
|
103
|
+
opt = options[idx]
|
|
104
|
+
label = opt[0] if isinstance(opt, tuple) else opt
|
|
105
|
+
desc = opt[1] if isinstance(opt, tuple) and len(opt) > 1 else ""
|
|
106
|
+
if label.strip().startswith("──"):
|
|
107
|
+
line = f" \033[2m{label}\033[0m"
|
|
108
|
+
elif idx == selected:
|
|
109
|
+
_accent = os.getenv("ARIA_ACCENT_COLOR", "192;128;80")
|
|
110
|
+
line = f" \033[1m\033[38;2;{_accent}m❯\033[0m \033[1m{label}\033[0m"
|
|
111
|
+
if desc:
|
|
112
|
+
line += f" \033[2m{desc}\033[0m"
|
|
113
|
+
else:
|
|
114
|
+
line = f" {label}"
|
|
115
|
+
if desc:
|
|
116
|
+
line += f" \033[2m{desc}\033[0m"
|
|
117
|
+
buf += f"\033[2K{line}\n"
|
|
118
|
+
phys_height += _physical_lines(line)
|
|
119
|
+
|
|
120
|
+
if n > visible:
|
|
121
|
+
hint = f" \033[2m{selected + 1}/{n}\033[0m"
|
|
122
|
+
buf += f"\033[2K{hint}\n"
|
|
123
|
+
else:
|
|
124
|
+
buf += "\033[2K\n"
|
|
125
|
+
phys_height += 1
|
|
126
|
+
|
|
127
|
+
_render.last_phys_height = phys_height
|
|
128
|
+
_raw(buf)
|
|
129
|
+
_render.drawn = True
|
|
130
|
+
|
|
131
|
+
_render.drawn = False
|
|
132
|
+
_render.last_phys_height = visible + 1
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
_esc_watcher.pause()
|
|
136
|
+
tty.setcbreak(fd)
|
|
137
|
+
sys.stdout.flush()
|
|
138
|
+
|
|
139
|
+
# Top boundary
|
|
140
|
+
_raw(f"\n \033[2m{_rule}\033[0m\n")
|
|
141
|
+
if title:
|
|
142
|
+
_raw(f" \033[1m{title}\033[0m \033[2m{controls_hint}\033[0m\n\n")
|
|
143
|
+
else:
|
|
144
|
+
_raw(f" \033[2m{controls_hint}\033[0m\n\n")
|
|
145
|
+
|
|
146
|
+
_render()
|
|
147
|
+
|
|
148
|
+
while True:
|
|
149
|
+
ch = os.read(fd, 1)
|
|
150
|
+
if ch == b'\x1b':
|
|
151
|
+
seq = b''
|
|
152
|
+
if _select.select([fd], [], [], 0.05)[0]:
|
|
153
|
+
seq = os.read(fd, 2)
|
|
154
|
+
if seq == b'[A':
|
|
155
|
+
selected = (selected - 1) % n; _render()
|
|
156
|
+
elif seq == b'[B':
|
|
157
|
+
selected = (selected + 1) % n; _render()
|
|
158
|
+
elif seq == b'[5~':
|
|
159
|
+
selected = max(0, selected - visible); _render()
|
|
160
|
+
elif seq == b'[6~':
|
|
161
|
+
selected = min(n - 1, selected + visible); _render()
|
|
162
|
+
elif not seq:
|
|
163
|
+
return -1
|
|
164
|
+
elif ch in (b'\r', b'\n'):
|
|
165
|
+
return selected
|
|
166
|
+
elif ch == b'q':
|
|
167
|
+
return -1
|
|
168
|
+
elif ch == b'k':
|
|
169
|
+
selected = (selected - 1) % n; _render()
|
|
170
|
+
elif ch == b'j':
|
|
171
|
+
selected = (selected + 1) % n; _render()
|
|
172
|
+
elif ch == b'g':
|
|
173
|
+
selected = 0; _render()
|
|
174
|
+
elif ch == b'G':
|
|
175
|
+
selected = n - 1; _render()
|
|
176
|
+
elif ch in (b'\x03', b'\x04'):
|
|
177
|
+
return -1
|
|
178
|
+
except (EOFError, KeyboardInterrupt, OSError):
|
|
179
|
+
return -1
|
|
180
|
+
finally:
|
|
181
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
|
182
|
+
_esc_watcher.resume()
|
|
183
|
+
_raw(f" \033[2m{_rule}\033[0m\n\n")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
async def run_picker_in_thread(options: list, current_idx: int,
|
|
187
|
+
title: str, max_visible: int = 14,
|
|
188
|
+
controls_hint: str = "↑↓ Enter Esc/q Cancel") -> int:
|
|
189
|
+
"""Run arrow_select in an executor thread to avoid kqueue conflicts on macOS."""
|
|
190
|
+
loop = asyncio.get_running_loop()
|
|
191
|
+
return await loop.run_in_executor(
|
|
192
|
+
None,
|
|
193
|
+
lambda: arrow_select(
|
|
194
|
+
options, current_idx, title, max_visible, controls_hint
|
|
195
|
+
),
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
# Back-compat aliases used by aria_cli.py
|
|
200
|
+
_arrow_select = arrow_select
|
|
201
|
+
_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
|
+
]
|