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,85 @@
|
|
|
1
|
+
"""Domain packs — subject areas that plug into a domain-neutral core.
|
|
2
|
+
|
|
3
|
+
The core knows about code, documents, data, and conversation. Everything that
|
|
4
|
+
belongs to a subject area — the identifiers it uses, the tools that act on
|
|
5
|
+
them, the guidance a model needs to reason about them — lives in a pack and is
|
|
6
|
+
switched on only when the user's message names something that pack recognises.
|
|
7
|
+
|
|
8
|
+
Adding a domain means adding a pack. It does not mean adding a branch to a
|
|
9
|
+
router, an intent label to the classifier, or a handler to a chain that every
|
|
10
|
+
message walks.
|
|
11
|
+
|
|
12
|
+
See ``aria_code.packs.base`` for the contract and ``aria_code.packs.registry``
|
|
13
|
+
for the activation rule.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from aria_code.packs.base import (
|
|
19
|
+
DEFAULT_ACTIVATION_THRESHOLD,
|
|
20
|
+
BaseDomainPack,
|
|
21
|
+
DomainPack,
|
|
22
|
+
EntityMatch,
|
|
23
|
+
PackActivation,
|
|
24
|
+
)
|
|
25
|
+
from aria_code.packs.registry import (
|
|
26
|
+
activate_packs,
|
|
27
|
+
active_acceptance_commands,
|
|
28
|
+
active_handlers,
|
|
29
|
+
active_prompt_fragments,
|
|
30
|
+
active_tool_names,
|
|
31
|
+
clear_registry,
|
|
32
|
+
get_pack,
|
|
33
|
+
register_pack,
|
|
34
|
+
registered_packs,
|
|
35
|
+
unregister_pack,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
_BUILTIN_LOADED = False
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def load_builtin_packs() -> tuple[str, ...]:
|
|
42
|
+
"""Register the packs that ship with Aria. Idempotent.
|
|
43
|
+
|
|
44
|
+
Finance is a built-in for continuity, not for precedence — it registers
|
|
45
|
+
through the same contract any third-party pack would use, and so do the
|
|
46
|
+
rest. Each is loaded in its own try/except because the cost of one broken
|
|
47
|
+
pack must be that pack, not the session.
|
|
48
|
+
"""
|
|
49
|
+
global _BUILTIN_LOADED
|
|
50
|
+
if not _BUILTIN_LOADED:
|
|
51
|
+
for module in ("finance", "logistics", "payments", "realty"):
|
|
52
|
+
try:
|
|
53
|
+
__import__(f"aria_code.packs.{module}", fromlist=["register"]).register()
|
|
54
|
+
except Exception: # pragma: no cover - a broken pack must not block startup
|
|
55
|
+
pass
|
|
56
|
+
_BUILTIN_LOADED = True
|
|
57
|
+
return tuple(getattr(p, "name", "") for p in registered_packs())
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def reset_builtin_packs() -> None:
|
|
61
|
+
"""Clear the registry and allow built-ins to load again (tests)."""
|
|
62
|
+
global _BUILTIN_LOADED
|
|
63
|
+
clear_registry()
|
|
64
|
+
_BUILTIN_LOADED = False
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
__all__ = [
|
|
68
|
+
"DEFAULT_ACTIVATION_THRESHOLD",
|
|
69
|
+
"BaseDomainPack",
|
|
70
|
+
"DomainPack",
|
|
71
|
+
"EntityMatch",
|
|
72
|
+
"PackActivation",
|
|
73
|
+
"activate_packs",
|
|
74
|
+
"active_acceptance_commands",
|
|
75
|
+
"active_handlers",
|
|
76
|
+
"active_prompt_fragments",
|
|
77
|
+
"active_tool_names",
|
|
78
|
+
"clear_registry",
|
|
79
|
+
"get_pack",
|
|
80
|
+
"load_builtin_packs",
|
|
81
|
+
"register_pack",
|
|
82
|
+
"registered_packs",
|
|
83
|
+
"reset_builtin_packs",
|
|
84
|
+
"unregister_pack",
|
|
85
|
+
]
|
aria_code/packs/base.py
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""The domain pack contract.
|
|
2
|
+
|
|
3
|
+
A domain pack bundles everything Aria needs to serve one subject area —
|
|
4
|
+
finance, logistics, clinical, accounting — behind a single interface, so the
|
|
5
|
+
core never learns any of them.
|
|
6
|
+
|
|
7
|
+
Why this exists
|
|
8
|
+
---------------
|
|
9
|
+
Finance was not a layer in this codebase; it was the substrate. ``finance``
|
|
10
|
+
and ``analysis`` were core intent labels, ~8,000 lines of ticker tables and
|
|
11
|
+
market handlers sat under ``apps/cli``, and the deterministic chain ran the
|
|
12
|
+
strategy, realty, and stock-chart handlers against *every* message before the
|
|
13
|
+
model saw it. The costs were concrete: a question about this repository was
|
|
14
|
+
answered with a MongoDB stock quote (the string "MongoDB" in a previous reply
|
|
15
|
+
resolved to the ticker MDB), and a message containing the word "行情" blocked
|
|
16
|
+
the REPL for tens of seconds downloading the full A-share and HK symbol
|
|
17
|
+
universe. A logistics or clinical user would have paid exactly the same tax.
|
|
18
|
+
|
|
19
|
+
The rule that prevents all of it
|
|
20
|
+
--------------------------------
|
|
21
|
+
**A pack activates only when it resolves a concrete entity from the user's own
|
|
22
|
+
message.** Domain vocabulary alone never activates a pack. "分析" is ordinary
|
|
23
|
+
Chinese; "AAPL" is a ticker. Only the second may switch on the finance pack,
|
|
24
|
+
and nothing a *previous assistant reply* said can switch on anything.
|
|
25
|
+
|
|
26
|
+
That single rule is what makes packs composable: an inactive pack contributes
|
|
27
|
+
no handlers, no tools, and no prompt text, so N domains cost O(N) to maintain
|
|
28
|
+
and O(1) at request time rather than N×M branches in one router.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
from dataclasses import dataclass, field
|
|
34
|
+
from typing import Protocol, Sequence, runtime_checkable
|
|
35
|
+
|
|
36
|
+
# A pack must clear this to activate. Resolvers report how sure they are that
|
|
37
|
+
# the surface text really names an entity of their kind; a bare uppercase word
|
|
38
|
+
# that merely *looks* like a ticker should score below it.
|
|
39
|
+
DEFAULT_ACTIVATION_THRESHOLD = 0.5
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class EntityMatch:
|
|
44
|
+
"""One concrete thing a pack recognised in a message.
|
|
45
|
+
|
|
46
|
+
``value`` is the canonical identifier the pack's tools accept (a ticker, a
|
|
47
|
+
waybill number, an ICD code). ``surface`` is the text as the user actually
|
|
48
|
+
wrote it, kept so the UI can show what was matched and the user can correct
|
|
49
|
+
a wrong resolution.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
pack: str
|
|
53
|
+
kind: str
|
|
54
|
+
value: str
|
|
55
|
+
surface: str = ""
|
|
56
|
+
position: int = 0
|
|
57
|
+
confidence: float = 1.0
|
|
58
|
+
|
|
59
|
+
def __post_init__(self) -> None:
|
|
60
|
+
if not self.pack:
|
|
61
|
+
raise ValueError("EntityMatch.pack is required")
|
|
62
|
+
if not self.kind:
|
|
63
|
+
raise ValueError("EntityMatch.kind is required")
|
|
64
|
+
if not self.value:
|
|
65
|
+
raise ValueError("EntityMatch.value is required")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass(frozen=True)
|
|
69
|
+
class PackActivation:
|
|
70
|
+
"""A pack that claimed the message, with what it claimed."""
|
|
71
|
+
|
|
72
|
+
pack: str
|
|
73
|
+
entities: tuple[EntityMatch, ...] = field(default_factory=tuple)
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def confidence(self) -> float:
|
|
77
|
+
return max((e.confidence for e in self.entities), default=0.0)
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def primary(self) -> EntityMatch | None:
|
|
81
|
+
"""Highest-confidence entity, earliest in the message on a tie."""
|
|
82
|
+
if not self.entities:
|
|
83
|
+
return None
|
|
84
|
+
return sorted(self.entities, key=lambda e: (-e.confidence, e.position))[0]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@runtime_checkable
|
|
88
|
+
class DomainPack(Protocol):
|
|
89
|
+
"""What a subject area must provide to plug into Aria.
|
|
90
|
+
|
|
91
|
+
Every method is optional beyond ``name`` and ``resolve_entities`` — a pack
|
|
92
|
+
that only teaches Aria to recognise its identifiers is already useful,
|
|
93
|
+
because recognition is what gates everything else.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
name: str
|
|
97
|
+
|
|
98
|
+
def resolve_entities(self, message: str) -> Sequence[EntityMatch]:
|
|
99
|
+
"""Return the entities this pack recognises in *message*.
|
|
100
|
+
|
|
101
|
+
Must be cheap and must not perform blocking network I/O: this runs on
|
|
102
|
+
every message, for every registered pack. Resolve from local tables or
|
|
103
|
+
a warm cache and return nothing when unsure — a missed activation is
|
|
104
|
+
recoverable, a wrong one silently answers the wrong question.
|
|
105
|
+
"""
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
def handlers(self) -> Sequence[object]:
|
|
109
|
+
"""Deterministic handlers, run only while this pack is active."""
|
|
110
|
+
...
|
|
111
|
+
|
|
112
|
+
def tool_names(self) -> Sequence[str]:
|
|
113
|
+
"""Tools to expose to the model only while this pack is active."""
|
|
114
|
+
...
|
|
115
|
+
|
|
116
|
+
def prompt_fragment(self, activation: PackActivation) -> str:
|
|
117
|
+
"""Domain guidance to add to the system prompt while active."""
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
def acceptance_commands(self, activation: PackActivation) -> Sequence[str]:
|
|
121
|
+
"""Commands that decide whether work in this domain is *correct*.
|
|
122
|
+
|
|
123
|
+
This is the pack's connection to the acceptance gate, and it is the
|
|
124
|
+
reason the pack contract scales past software. Every domain defines
|
|
125
|
+
"right" differently, but they all express it the same way: a command
|
|
126
|
+
that exits non-zero when the work is wrong. Software says
|
|
127
|
+
``pytest -q``; a logistics pack says "run the reconciliation script,
|
|
128
|
+
it exits non-zero when the ledger does not balance"; a data pack says
|
|
129
|
+
"validate against the schema".
|
|
130
|
+
|
|
131
|
+
So a pack does not have to teach the core its subject. It only has to
|
|
132
|
+
say what green looks like, and the closed loop it gets in return is
|
|
133
|
+
the same one the software case gets.
|
|
134
|
+
|
|
135
|
+
Returning nothing is the normal case: inference from the workspace
|
|
136
|
+
then decides, exactly as before.
|
|
137
|
+
"""
|
|
138
|
+
...
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class BaseDomainPack:
|
|
142
|
+
"""Convenience base implementing the optional half of the protocol."""
|
|
143
|
+
|
|
144
|
+
name: str = ""
|
|
145
|
+
|
|
146
|
+
def resolve_entities(self, message: str) -> Sequence[EntityMatch]:
|
|
147
|
+
raise NotImplementedError
|
|
148
|
+
|
|
149
|
+
def handlers(self) -> Sequence[object]:
|
|
150
|
+
return ()
|
|
151
|
+
|
|
152
|
+
def tool_names(self) -> Sequence[str]:
|
|
153
|
+
return ()
|
|
154
|
+
|
|
155
|
+
def prompt_fragment(self, activation: PackActivation) -> str:
|
|
156
|
+
return ""
|
|
157
|
+
|
|
158
|
+
def acceptance_commands(self, activation: PackActivation) -> Sequence[str]:
|
|
159
|
+
return ()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
__all__ = [
|
|
163
|
+
"DEFAULT_ACTIVATION_THRESHOLD",
|
|
164
|
+
"BaseDomainPack",
|
|
165
|
+
"DomainPack",
|
|
166
|
+
"EntityMatch",
|
|
167
|
+
"PackActivation",
|
|
168
|
+
]
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"""Finance as a domain pack — the contract's first consumer.
|
|
2
|
+
|
|
3
|
+
This does not reimplement anything. It wraps the existing symbol resolution
|
|
4
|
+
and deterministic handlers so finance stops being the substrate and becomes one
|
|
5
|
+
pack among peers. Behaviour is intended to be unchanged; the regression suites
|
|
6
|
+
in tests/test_market_history_inheritance.py and tests/test_intent_signals.py
|
|
7
|
+
are the safety net for that claim.
|
|
8
|
+
|
|
9
|
+
What changes is *reach*. Previously the strategy, realty, and stock-chart
|
|
10
|
+
handlers ran against every message in the deterministic chain, before the model
|
|
11
|
+
saw it. Behind the contract they run only when this pack has resolved a real
|
|
12
|
+
financial entity from the user's message, so a logistics or clinical question
|
|
13
|
+
never touches them.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Sequence
|
|
19
|
+
|
|
20
|
+
from aria_code.packs.base import BaseDomainPack, EntityMatch, PackActivation
|
|
21
|
+
|
|
22
|
+
PACK_NAME = "finance"
|
|
23
|
+
|
|
24
|
+
# Tools this pack owns. Exposed to the model only while the pack is active, so
|
|
25
|
+
# a code session is not offered a quote tool it can misfire (which is how a
|
|
26
|
+
# repository question became a MongoDB stock lookup).
|
|
27
|
+
# The tools this pack owns, derived from the registries that register them
|
|
28
|
+
# rather than hand-listed. A hand-written tuple drifts the moment a tool is
|
|
29
|
+
# added or renamed, and both failure directions are silent: a tool left out
|
|
30
|
+
# stays exposed on every turn, and a tool named wrongly promises a capability
|
|
31
|
+
# that does not exist (this list said "run_backtest"; the registered name is
|
|
32
|
+
# "backtest_strategy").
|
|
33
|
+
_EXTRA_FINANCE_TOOLS = (
|
|
34
|
+
# Registered by the static schema block and the broker/market modules
|
|
35
|
+
# rather than by LOCAL_FINANCE_TOOL_REGISTRY.
|
|
36
|
+
"get_market_data",
|
|
37
|
+
"get_market_history",
|
|
38
|
+
"broker_query",
|
|
39
|
+
"broker_order",
|
|
40
|
+
"get_broker_portfolio",
|
|
41
|
+
"analyze_news",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _finance_tool_names() -> tuple[str, ...]:
|
|
46
|
+
names: list[str] = []
|
|
47
|
+
try:
|
|
48
|
+
from aria_code.tools.local_finance_tools import LOCAL_FINANCE_TOOL_REGISTRY
|
|
49
|
+
|
|
50
|
+
names.extend(LOCAL_FINANCE_TOOL_REGISTRY)
|
|
51
|
+
except Exception:
|
|
52
|
+
pass
|
|
53
|
+
for name in _EXTRA_FINANCE_TOOLS:
|
|
54
|
+
if name not in names:
|
|
55
|
+
names.append(name)
|
|
56
|
+
return tuple(names)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
FINANCE_TOOLS = _finance_tool_names()
|
|
60
|
+
|
|
61
|
+
# A bare uppercase run merely *looks* like a ticker — "EMS", "ESB", and "MDB"
|
|
62
|
+
# all appeared in an architecture diagram in the incident that motivated this
|
|
63
|
+
# contract. Resolution against a real symbol table scores high; a shape-only
|
|
64
|
+
# guess scores below the activation threshold and therefore does not switch the
|
|
65
|
+
# pack on by itself.
|
|
66
|
+
_RESOLVED_CONFIDENCE = 0.95
|
|
67
|
+
_SHAPE_ONLY_CONFIDENCE = 0.3
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _resolve_symbols(message: str) -> list[tuple[str, str, int]]:
|
|
71
|
+
"""Return (canonical, surface, position) for symbols named in *message*."""
|
|
72
|
+
try:
|
|
73
|
+
from aria_code.apps.cli.market_universe import resolve_market_mentions
|
|
74
|
+
except Exception:
|
|
75
|
+
return []
|
|
76
|
+
try:
|
|
77
|
+
hits = resolve_market_mentions(message, limit=6)
|
|
78
|
+
except Exception:
|
|
79
|
+
return []
|
|
80
|
+
out: list[tuple[str, str, int]] = []
|
|
81
|
+
for position, item in hits:
|
|
82
|
+
symbol = str(getattr(item, "symbol", "") or "").strip()
|
|
83
|
+
if symbol:
|
|
84
|
+
out.append((symbol.upper(), str(getattr(item, "name", "") or ""), position))
|
|
85
|
+
return out
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Bare uppercase runs are resolved against an ALLOWLIST, not a blocklist.
|
|
89
|
+
# market_detect takes the opposite approach — it rejects known non-tickers like
|
|
90
|
+
# BUY and SELL — which is why "MongoDB" in an architecture sentence resolved to
|
|
91
|
+
# the ticker MDB: nothing had thought to forbid it. An allowlist fails closed:
|
|
92
|
+
# an unknown uppercase word scores below the activation threshold, so the worst
|
|
93
|
+
# case is a missed activation the user can force with "$MDB".
|
|
94
|
+
_KNOWN_TICKERS = frozenset({
|
|
95
|
+
# US mega/large cap
|
|
96
|
+
"AAPL", "MSFT", "GOOG", "GOOGL", "AMZN", "META", "TSLA", "NVDA", "AVGO",
|
|
97
|
+
"BRK.A", "BRK.B", "JPM", "V", "MA", "UNH", "XOM", "WMT", "JNJ", "PG",
|
|
98
|
+
"HD", "COST", "ORCL", "CRM", "AMD", "INTC", "CSCO", "ADBE", "NFLX",
|
|
99
|
+
"PEP", "KO", "MCD", "NKE", "DIS", "BA", "CAT", "GE", "GS", "MS",
|
|
100
|
+
"BAC", "WFC", "C", "T", "VZ", "PFE", "MRK", "ABBV", "LLY", "TMO",
|
|
101
|
+
"PLTR", "SNOW", "UBER", "ABNB", "COIN", "SHOP", "SQ", "PYPL", "SMCI",
|
|
102
|
+
"MU", "QCOM", "TXN", "AMAT", "LRCX", "KLAC", "ARM", "TSM", "ASML",
|
|
103
|
+
# Common ETFs
|
|
104
|
+
"SPY", "QQQ", "IWM", "DIA", "VOO", "VTI", "GLD", "SLV", "USO", "TLT",
|
|
105
|
+
"ARKK", "XLF", "XLE", "XLK", "SOXL", "TQQQ", "SQQQ", "HYG", "EEM",
|
|
106
|
+
# China ADRs
|
|
107
|
+
"BABA", "JD", "PDD", "NIO", "LI", "XPEV", "BIDU", "TME", "BILI", "NTES",
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _bare_uppercase_runs(message: str) -> list[tuple[str, str, int, float]]:
|
|
112
|
+
"""Uppercase runs, scored by whether they are recognised or merely shaped.
|
|
113
|
+
|
|
114
|
+
A recognised ticker activates the pack. An unrecognised run is still
|
|
115
|
+
reported, at a confidence below the activation threshold, so the CLI can
|
|
116
|
+
offer "did you mean $MDB?" without answering a code question with a stock
|
|
117
|
+
quote on its own initiative.
|
|
118
|
+
"""
|
|
119
|
+
import re
|
|
120
|
+
|
|
121
|
+
out: list[tuple[str, str, int, float]] = []
|
|
122
|
+
for match in re.finditer(r"(?<![A-Za-z0-9$])([A-Z]{1,5})(?![A-Za-z0-9])", message or ""):
|
|
123
|
+
candidate = match.group(1)
|
|
124
|
+
confidence = (
|
|
125
|
+
_RESOLVED_CONFIDENCE if candidate in _KNOWN_TICKERS else _SHAPE_ONLY_CONFIDENCE
|
|
126
|
+
)
|
|
127
|
+
out.append((candidate, candidate, match.start(), confidence))
|
|
128
|
+
return out
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _explicit_ticker(message: str) -> list[tuple[str, str, int]]:
|
|
132
|
+
"""Tickers written in a form that states the intent explicitly.
|
|
133
|
+
|
|
134
|
+
``$AAPL`` and a bare A-share code are unambiguous. A bare uppercase word
|
|
135
|
+
is not, and is deliberately excluded here.
|
|
136
|
+
"""
|
|
137
|
+
import re
|
|
138
|
+
|
|
139
|
+
out: list[tuple[str, str, int]] = []
|
|
140
|
+
for match in re.finditer(r"\$([A-Za-z]{1,5})(?![A-Za-z0-9])", message or ""):
|
|
141
|
+
out.append((match.group(1).upper(), match.group(0), match.start()))
|
|
142
|
+
for match in re.finditer(r"(?<!\d)((?:60|68|00|30)\d{4})(?!\d)", message or ""):
|
|
143
|
+
out.append((match.group(1), match.group(0), match.start()))
|
|
144
|
+
return out
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class FinancePack(BaseDomainPack):
|
|
148
|
+
"""Recognises tradable instruments and owns the market workflows."""
|
|
149
|
+
|
|
150
|
+
name = PACK_NAME
|
|
151
|
+
|
|
152
|
+
def resolve_entities(self, message: str) -> Sequence[EntityMatch]:
|
|
153
|
+
if not (message or "").strip():
|
|
154
|
+
return ()
|
|
155
|
+
|
|
156
|
+
seen: set[str] = set()
|
|
157
|
+
entities: list[EntityMatch] = []
|
|
158
|
+
|
|
159
|
+
for value, surface, position in _explicit_ticker(message):
|
|
160
|
+
if value in seen:
|
|
161
|
+
continue
|
|
162
|
+
seen.add(value)
|
|
163
|
+
entities.append(EntityMatch(
|
|
164
|
+
pack=PACK_NAME, kind="instrument", value=value,
|
|
165
|
+
surface=surface, position=position,
|
|
166
|
+
confidence=_RESOLVED_CONFIDENCE,
|
|
167
|
+
))
|
|
168
|
+
|
|
169
|
+
for value, surface, position, confidence in _bare_uppercase_runs(message):
|
|
170
|
+
if value in seen:
|
|
171
|
+
continue
|
|
172
|
+
seen.add(value)
|
|
173
|
+
entities.append(EntityMatch(
|
|
174
|
+
pack=PACK_NAME, kind="instrument", value=value,
|
|
175
|
+
surface=surface, position=position,
|
|
176
|
+
confidence=confidence,
|
|
177
|
+
))
|
|
178
|
+
|
|
179
|
+
for value, surface, position in _resolve_symbols(message):
|
|
180
|
+
if value in seen:
|
|
181
|
+
continue
|
|
182
|
+
seen.add(value)
|
|
183
|
+
entities.append(EntityMatch(
|
|
184
|
+
pack=PACK_NAME, kind="instrument", value=value,
|
|
185
|
+
surface=surface or value, position=position,
|
|
186
|
+
confidence=_RESOLVED_CONFIDENCE,
|
|
187
|
+
))
|
|
188
|
+
|
|
189
|
+
return tuple(entities)
|
|
190
|
+
|
|
191
|
+
def handlers(self) -> Sequence[object]:
|
|
192
|
+
"""The entity-dependent handlers, reachable only when active.
|
|
193
|
+
|
|
194
|
+
``handle_stock_chart_analysis`` takes two keyword-only collaborators
|
|
195
|
+
and cannot be called as ``handler(message)``. Returning it bare made
|
|
196
|
+
every finance-activated turn die with a TypeError inside the
|
|
197
|
+
deterministic chain — the chain calls handlers uniformly, so a handler
|
|
198
|
+
that does not fit that shape is not a handler. Bound here, the way
|
|
199
|
+
``deterministic._handle_stock_chart_analysis`` already bound it before
|
|
200
|
+
the pack layer took the call over.
|
|
201
|
+
"""
|
|
202
|
+
try:
|
|
203
|
+
from aria_code.apps.cli.handlers.chart_handlers import (
|
|
204
|
+
handle_stock_chart_analysis,
|
|
205
|
+
)
|
|
206
|
+
from aria_code.apps.cli.utils.market_detect import (
|
|
207
|
+
_extract_market_symbol,
|
|
208
|
+
_is_stock_chart_analysis_request,
|
|
209
|
+
)
|
|
210
|
+
except Exception:
|
|
211
|
+
return ()
|
|
212
|
+
|
|
213
|
+
def _chart(message: str) -> dict:
|
|
214
|
+
return handle_stock_chart_analysis(
|
|
215
|
+
message,
|
|
216
|
+
is_chart_request=_is_stock_chart_analysis_request,
|
|
217
|
+
extract_symbol=_extract_market_symbol,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Only the chart handler. handle_strategy_advice does not belong
|
|
221
|
+
# behind the entity gate — see deterministic._SELF_GATED_HANDLERS.
|
|
222
|
+
return (_chart,)
|
|
223
|
+
|
|
224
|
+
def tool_names(self) -> Sequence[str]:
|
|
225
|
+
return FINANCE_TOOLS
|
|
226
|
+
|
|
227
|
+
def prompt_fragment(self, activation: PackActivation) -> str:
|
|
228
|
+
primary = activation.primary
|
|
229
|
+
if primary is None:
|
|
230
|
+
return ""
|
|
231
|
+
symbols = ", ".join(sorted({e.value for e in activation.entities}))
|
|
232
|
+
return (
|
|
233
|
+
f"金融标的已识别:{symbols}。\n"
|
|
234
|
+
"使用工具取回的数据回答,不要凭记忆给出价格或指标;"
|
|
235
|
+
"标注数据来源与时间戳;输出不构成投资建议。"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
FINANCE_PACK = FinancePack()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def register() -> FinancePack:
|
|
243
|
+
"""Register the finance pack. Idempotent."""
|
|
244
|
+
from aria_code.packs.registry import register_pack
|
|
245
|
+
|
|
246
|
+
register_pack(FINANCE_PACK)
|
|
247
|
+
return FINANCE_PACK
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
__all__ = ["FINANCE_PACK", "FINANCE_TOOLS", "PACK_NAME", "FinancePack", "register"]
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""Logistics — waybills, containers, carriers.
|
|
2
|
+
|
|
3
|
+
What makes this pack safe to have switched on is that every identifier it
|
|
4
|
+
recognises is *verifiable*, not merely shaped right. A bare run of twelve
|
|
5
|
+
digits appears in invoices, timestamps, phone numbers and order IDs; a
|
|
6
|
+
container number carries a check digit that can be recomputed, and a UPS or SF
|
|
7
|
+
tracking number carries a prefix that nothing else uses.
|
|
8
|
+
|
|
9
|
+
So the resolver reports both kinds and scores them differently: verified
|
|
10
|
+
identifiers activate the pack, shape-only matches are reported below the
|
|
11
|
+
activation threshold so the CLI can offer "did you mean this waybill?" without
|
|
12
|
+
answering a code question with a shipment lookup on its own initiative. That
|
|
13
|
+
asymmetry is the contract's rule applied to a domain whose identifiers are
|
|
14
|
+
almost all digits.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import re
|
|
20
|
+
from typing import Sequence
|
|
21
|
+
|
|
22
|
+
from aria_code.packs.base import BaseDomainPack, EntityMatch, PackActivation
|
|
23
|
+
|
|
24
|
+
PACK_NAME = "logistics"
|
|
25
|
+
|
|
26
|
+
LOGISTICS_TOOLS = (
|
|
27
|
+
"analyze_logistics_data",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
_VERIFIED = 0.95
|
|
31
|
+
_SHAPE_ONLY = 0.3
|
|
32
|
+
|
|
33
|
+
# Carrier prefixes that no other identifier uses.
|
|
34
|
+
_CARRIER_PATTERNS: tuple[tuple[str, re.Pattern], ...] = (
|
|
35
|
+
# UPS: 1Z + 6-char shipper + 2-char service + 8-digit sequence.
|
|
36
|
+
("ups", re.compile(r"\b(1Z[0-9A-Z]{16})\b", re.I)),
|
|
37
|
+
# SF Express domestic waybill.
|
|
38
|
+
("sf", re.compile(r"\b(SF\d{12,15})\b", re.I)),
|
|
39
|
+
# DHL express, 'JD' + 20 digits (also used on some waybill labels).
|
|
40
|
+
("dhl", re.compile(r"\b(JD\d{18,20})\b")),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# ISO 6346 container: 4 letters (owner + category) + 6 digits + check digit.
|
|
44
|
+
_CONTAINER = re.compile(r"\b([A-Z]{4}\d{7})\b")
|
|
45
|
+
|
|
46
|
+
# Bare numeric runs — the shape most domestic waybills take, and also the shape
|
|
47
|
+
# of an order id, an invoice number and a unix timestamp in milliseconds.
|
|
48
|
+
_BARE_DIGITS = re.compile(r"(?<!\d)(\d{10,15})(?!\d)")
|
|
49
|
+
|
|
50
|
+
# ISO 6346 letter values: A=10, then ascending, skipping every multiple of 11.
|
|
51
|
+
def _iso6346_letter_values() -> dict[str, int]:
|
|
52
|
+
values: dict[str, int] = {}
|
|
53
|
+
value = 10
|
|
54
|
+
for index in range(26):
|
|
55
|
+
while value % 11 == 0:
|
|
56
|
+
value += 1
|
|
57
|
+
values[chr(ord("A") + index)] = value
|
|
58
|
+
value += 1
|
|
59
|
+
return values
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
_LETTER_VALUES = _iso6346_letter_values()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def is_valid_container(code: str) -> bool:
|
|
66
|
+
"""True when *code* satisfies the ISO 6346 check digit.
|
|
67
|
+
|
|
68
|
+
This is what separates a container number from four capitals followed by
|
|
69
|
+
seven digits, which is also the shape of plenty of part numbers and
|
|
70
|
+
internal SKUs. Recomputing the check digit turns a guess into a
|
|
71
|
+
resolution — the distinction the pack contract is built on.
|
|
72
|
+
"""
|
|
73
|
+
text = (code or "").strip().upper()
|
|
74
|
+
if len(text) != 11 or not text[:4].isalpha() or not text[4:].isdigit():
|
|
75
|
+
return False
|
|
76
|
+
total = 0
|
|
77
|
+
for position, char in enumerate(text[:10]):
|
|
78
|
+
value = _LETTER_VALUES[char] if char.isalpha() else int(char)
|
|
79
|
+
total += value * (2 ** position)
|
|
80
|
+
return (total % 11) % 10 == int(text[10])
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class LogisticsPack(BaseDomainPack):
|
|
84
|
+
"""Recognises shipment identifiers and owns the freight workflows."""
|
|
85
|
+
|
|
86
|
+
name = PACK_NAME
|
|
87
|
+
|
|
88
|
+
def resolve_entities(self, message: str) -> Sequence[EntityMatch]:
|
|
89
|
+
text = message or ""
|
|
90
|
+
if not text.strip():
|
|
91
|
+
return ()
|
|
92
|
+
|
|
93
|
+
seen: set[str] = set()
|
|
94
|
+
claimed: list[tuple[int, int]] = []
|
|
95
|
+
entities: list[EntityMatch] = []
|
|
96
|
+
|
|
97
|
+
def _add(value: str, kind: str, surface: str, span: tuple[int, int], confidence: float) -> None:
|
|
98
|
+
if value in seen:
|
|
99
|
+
return
|
|
100
|
+
seen.add(value)
|
|
101
|
+
claimed.append(span)
|
|
102
|
+
entities.append(EntityMatch(
|
|
103
|
+
pack=PACK_NAME, kind=kind, value=value,
|
|
104
|
+
surface=surface, position=span[0], confidence=confidence,
|
|
105
|
+
))
|
|
106
|
+
|
|
107
|
+
for carrier, pattern in _CARRIER_PATTERNS:
|
|
108
|
+
for match in pattern.finditer(text):
|
|
109
|
+
_add(match.group(1).upper(), f"waybill:{carrier}",
|
|
110
|
+
match.group(1), match.span(1), _VERIFIED)
|
|
111
|
+
|
|
112
|
+
for match in _CONTAINER.finditer(text):
|
|
113
|
+
code = match.group(1)
|
|
114
|
+
_add(code, "container", code, match.span(1),
|
|
115
|
+
_VERIFIED if is_valid_container(code) else _SHAPE_ONLY)
|
|
116
|
+
|
|
117
|
+
# Bare digit runs last, and only outside what a verified identifier
|
|
118
|
+
# already claimed: the digits inside `1Z999AA10123456784` are not a
|
|
119
|
+
# second, weaker waybill, and reporting them as one would let the UI
|
|
120
|
+
# offer a "did you mean" for a number the user never wrote.
|
|
121
|
+
for match in _BARE_DIGITS.finditer(text):
|
|
122
|
+
start, end = match.span(1)
|
|
123
|
+
if any(start >= c_start and end <= c_end for c_start, c_end in claimed):
|
|
124
|
+
continue
|
|
125
|
+
_add(match.group(1), "waybill", match.group(1), match.span(1), _SHAPE_ONLY)
|
|
126
|
+
|
|
127
|
+
return tuple(entities)
|
|
128
|
+
|
|
129
|
+
def tool_names(self) -> Sequence[str]:
|
|
130
|
+
return LOGISTICS_TOOLS
|
|
131
|
+
|
|
132
|
+
def prompt_fragment(self, activation: PackActivation) -> str:
|
|
133
|
+
kinds = sorted({e.kind for e in activation.entities})
|
|
134
|
+
ids = ", ".join(sorted({e.value for e in activation.entities}))
|
|
135
|
+
return (
|
|
136
|
+
f"物流标识已识别({', '.join(kinds)}):{ids}。\n"
|
|
137
|
+
"用工具取回的运单/箱单数据回答,不要凭记忆编造承运商、时效或费率;"
|
|
138
|
+
"标注数据来源与时间戳。金额与账期以对账结果为准。"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def acceptance_commands(self, activation: PackActivation) -> Sequence[str]:
|
|
142
|
+
# Looked up through the module rather than a name bound at import, so
|
|
143
|
+
# what this workspace declares is read when the turn runs — a .ariarc
|
|
144
|
+
# edited mid-session takes effect on the next message, not the next
|
|
145
|
+
# process.
|
|
146
|
+
from aria_code.packs import rules
|
|
147
|
+
|
|
148
|
+
return rules.acceptance_commands_for(PACK_NAME)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
LOGISTICS_PACK = LogisticsPack()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def register() -> LogisticsPack:
|
|
155
|
+
"""Register the logistics pack. Idempotent."""
|
|
156
|
+
from aria_code.packs.registry import register_pack
|
|
157
|
+
|
|
158
|
+
register_pack(LOGISTICS_PACK)
|
|
159
|
+
return LOGISTICS_PACK
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
__all__ = [
|
|
163
|
+
"LOGISTICS_PACK",
|
|
164
|
+
"LOGISTICS_TOOLS",
|
|
165
|
+
"PACK_NAME",
|
|
166
|
+
"LogisticsPack",
|
|
167
|
+
"is_valid_container",
|
|
168
|
+
"register",
|
|
169
|
+
]
|