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,388 @@
|
|
|
1
|
+
"""
|
|
2
|
+
spreadsheet_tools.py — 结构化 Excel 工作簿生成 + 独立校验
|
|
3
|
+
==========================================================
|
|
4
|
+
输入: 结构化 spec(多工作表 / 表头 / 数据行 / 合计声明)
|
|
5
|
+
输出: 带样式与公式的 .xlsx(默认落盘到 artifacts 产物目录)
|
|
6
|
+
|
|
7
|
+
设计原则(与 /report 研报引擎同一哲学:确定性优先):
|
|
8
|
+
· **公式由工具生成,不由模型手写** —— 模型只声明意图
|
|
9
|
+
("对 F 列按 E 列=GBP 条件求和"),SUMIFS/COUNTIF 的单元格范围
|
|
10
|
+
由工具按实际数据行数计算,从根源上消灭"范围错位"这类静默错误。
|
|
11
|
+
· **Python 独立复核** —— 每个合计公式落盘的同时,用纯 Python 对
|
|
12
|
+
同一数据重算一遍,结果随返回值给出;两条路径殊途同归才算可信。
|
|
13
|
+
· **禁止硬编码合计** —— 合计单元格只写公式,Excel/Numbers 打开时
|
|
14
|
+
即时计算,数据行修改后合计自动跟随。
|
|
15
|
+
· 样式约定内置(Arial、深色表头、千分位、冻结首行、标黄高亮),
|
|
16
|
+
模型无需(也不能)逐单元格调样式。
|
|
17
|
+
|
|
18
|
+
对外暴露:
|
|
19
|
+
write_workbook(spec, out_path=None) → dict(路径 + 校验结果)
|
|
20
|
+
tool_write_spreadsheet(params) → Agent 工具入口(JSON 安全)
|
|
21
|
+
register_spreadsheet_tools(tools, schemas) → 注册进 LOCAL_TOOLS
|
|
22
|
+
|
|
23
|
+
完全离线,无网络依赖;openpyxl 已在项目基础依赖中。
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import logging
|
|
29
|
+
import re
|
|
30
|
+
from datetime import date, datetime
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
from openpyxl import Workbook
|
|
38
|
+
from openpyxl.styles import Alignment, Border, Font, PatternFill, Side
|
|
39
|
+
from openpyxl.utils import get_column_letter, column_index_from_string
|
|
40
|
+
HAS_OPENPYXL = True
|
|
41
|
+
except ImportError: # pragma: no cover - openpyxl 在 pyproject 基础依赖中
|
|
42
|
+
HAS_OPENPYXL = False
|
|
43
|
+
|
|
44
|
+
# ── 样式约定(全局统一,勿逐表覆盖) ─────────────────────────────────────────
|
|
45
|
+
_FONT = "Arial"
|
|
46
|
+
_HDR_FILL = "1F2937" # 深灰蓝表头
|
|
47
|
+
_HIGHLIGHT_FILL = "FEF3C7" # 标黄:假设 / 待确认条目
|
|
48
|
+
_BORDER_COLOR = "D1D5DB"
|
|
49
|
+
_DATE_FMT = "yyyy-mm-dd"
|
|
50
|
+
_ISO_DATE = re.compile(r"^\d{4}-\d{2}-\d{2}$")
|
|
51
|
+
|
|
52
|
+
# Agent 工具防线(防止一次调用写出百万行拖死 REPL)
|
|
53
|
+
MAX_SHEETS = 12
|
|
54
|
+
MAX_ROWS_PER_SHEET = 5000
|
|
55
|
+
MAX_COLS = 40
|
|
56
|
+
|
|
57
|
+
_TOTAL_TYPES = ("sum", "sumif", "count", "countif", "average")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _styles():
|
|
61
|
+
thin = Side(style="thin", color=_BORDER_COLOR)
|
|
62
|
+
return {
|
|
63
|
+
"hdr_font": Font(name=_FONT, bold=True, color="FFFFFF", size=11),
|
|
64
|
+
"hdr_fill": PatternFill("solid", fgColor=_HDR_FILL),
|
|
65
|
+
"body": Font(name=_FONT, size=10),
|
|
66
|
+
"bold": Font(name=_FONT, bold=True, size=10),
|
|
67
|
+
"border": Border(left=thin, right=thin, top=thin, bottom=thin),
|
|
68
|
+
"hl_fill": PatternFill("solid", fgColor=_HIGHLIGHT_FILL),
|
|
69
|
+
"center": Alignment(horizontal="center", vertical="center"),
|
|
70
|
+
"wrap": Alignment(vertical="center", wrap_text=True),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _coerce_cell(value: Any) -> Any:
|
|
75
|
+
"""ISO 日期字符串 → date;其余原样。"""
|
|
76
|
+
if isinstance(value, str) and _ISO_DATE.match(value):
|
|
77
|
+
try:
|
|
78
|
+
return datetime.strptime(value, "%Y-%m-%d").date()
|
|
79
|
+
except ValueError:
|
|
80
|
+
return value
|
|
81
|
+
return value
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _col_idx(letter: str) -> int:
|
|
85
|
+
return column_index_from_string(letter.upper())
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# ── 合计公式:生成 + Python 复核(同一份声明,两条独立路径) ────────────────
|
|
89
|
+
|
|
90
|
+
def _total_formula(total: Dict[str, Any], first_row: int, last_row: int) -> str:
|
|
91
|
+
kind = str(total.get("type", "sum")).lower()
|
|
92
|
+
col = str(total["value_col"]).upper()
|
|
93
|
+
rng = f"{col}{first_row}:{col}{last_row}"
|
|
94
|
+
if kind == "sum":
|
|
95
|
+
return f"=SUM({rng})"
|
|
96
|
+
if kind == "average":
|
|
97
|
+
return f"=AVERAGE({rng})"
|
|
98
|
+
if kind == "count":
|
|
99
|
+
return f"=COUNTA({rng})"
|
|
100
|
+
key_col = str(total["key_col"]).upper()
|
|
101
|
+
key = str(total["key"])
|
|
102
|
+
key_rng = f"{key_col}{first_row}:{key_col}{last_row}"
|
|
103
|
+
if kind == "sumif":
|
|
104
|
+
return f'=SUMIFS({rng},{key_rng},"{key}")'
|
|
105
|
+
if kind == "countif":
|
|
106
|
+
return f'=COUNTIF({key_rng},"{key}")'
|
|
107
|
+
raise ValueError(f"unsupported total type: {kind}")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _total_python(total: Dict[str, Any], rows: List[List[Any]]) -> float:
|
|
111
|
+
"""对同一声明用纯 Python 重算 —— 与公式路径互为独立校验。"""
|
|
112
|
+
kind = str(total.get("type", "sum")).lower()
|
|
113
|
+
vi = _col_idx(str(total["value_col"])) - 1
|
|
114
|
+
|
|
115
|
+
def _nums(filtered):
|
|
116
|
+
for r in filtered:
|
|
117
|
+
v = r[vi] if vi < len(r) else None
|
|
118
|
+
if isinstance(v, (int, float)) and not isinstance(v, bool):
|
|
119
|
+
yield v
|
|
120
|
+
|
|
121
|
+
if kind in ("sum", "average", "count"):
|
|
122
|
+
picked = rows
|
|
123
|
+
else:
|
|
124
|
+
ki = _col_idx(str(total["key_col"])) - 1
|
|
125
|
+
key = str(total["key"])
|
|
126
|
+
picked = [r for r in rows if ki < len(r) and str(r[ki]) == key]
|
|
127
|
+
|
|
128
|
+
if kind == "count":
|
|
129
|
+
return float(sum(1 for r in picked if vi < len(r) and r[vi] not in (None, "")))
|
|
130
|
+
if kind == "countif":
|
|
131
|
+
return float(len(picked))
|
|
132
|
+
vals = list(_nums(picked))
|
|
133
|
+
if kind == "average":
|
|
134
|
+
return round(sum(vals) / len(vals), 6) if vals else 0.0
|
|
135
|
+
return round(sum(vals), 6)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# ── 核心:spec → Workbook ────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
def build_workbook(spec: Dict[str, Any]) -> Tuple["Workbook", List[Dict[str, Any]]]:
|
|
141
|
+
"""按 spec 构建 Workbook。返回 (wb, 校验清单)。
|
|
142
|
+
|
|
143
|
+
sheet spec 字段:
|
|
144
|
+
name 工作表名(必填)
|
|
145
|
+
headers 表头列表(必填)
|
|
146
|
+
rows 数据行(二维数组;ISO 日期字符串自动转日期)
|
|
147
|
+
number_formats {"F": "#,##0.00"} 列号→格式(可选)
|
|
148
|
+
col_widths [宽度…] 与表头对齐(可选)
|
|
149
|
+
freeze_header 冻结首行,默认 True
|
|
150
|
+
highlight_rows [1,5] 数据区内 1-based 行号,标黄(可选)
|
|
151
|
+
totals 合计声明列表(可选),元素:
|
|
152
|
+
{label, type: sum|sumif|count|countif|average,
|
|
153
|
+
value_col: "F", key_col: "E", key: "GBP",
|
|
154
|
+
label_col: "D"}
|
|
155
|
+
"""
|
|
156
|
+
if not HAS_OPENPYXL:
|
|
157
|
+
raise RuntimeError("openpyxl 未安装(应随基础依赖提供)")
|
|
158
|
+
|
|
159
|
+
st = _styles()
|
|
160
|
+
wb = Workbook()
|
|
161
|
+
wb.remove(wb.active)
|
|
162
|
+
verifications: List[Dict[str, Any]] = []
|
|
163
|
+
|
|
164
|
+
for sheet in spec.get("sheets", []):
|
|
165
|
+
name = str(sheet["name"])[:31] # Excel 工作表名 31 字符上限
|
|
166
|
+
ws = wb.create_sheet(name)
|
|
167
|
+
headers: List[str] = list(sheet.get("headers", []))
|
|
168
|
+
rows: List[List[Any]] = [list(r) for r in sheet.get("rows", [])]
|
|
169
|
+
|
|
170
|
+
ws.append(headers)
|
|
171
|
+
for c in ws[1]:
|
|
172
|
+
c.font, c.fill = st["hdr_font"], st["hdr_fill"]
|
|
173
|
+
c.alignment, c.border = st["center"], st["border"]
|
|
174
|
+
|
|
175
|
+
highlight = {int(i) for i in sheet.get("highlight_rows", [])}
|
|
176
|
+
for i, row in enumerate(rows, start=1):
|
|
177
|
+
ws.append([_coerce_cell(v) for v in row])
|
|
178
|
+
r = ws.max_row
|
|
179
|
+
for c in ws[r]:
|
|
180
|
+
c.font, c.border, c.alignment = st["body"], st["border"], st["wrap"]
|
|
181
|
+
if i in highlight:
|
|
182
|
+
for c in ws[r]:
|
|
183
|
+
c.fill = st["hl_fill"]
|
|
184
|
+
|
|
185
|
+
fmts: Dict[str, str] = dict(sheet.get("number_formats", {}))
|
|
186
|
+
for letter, fmt in fmts.items():
|
|
187
|
+
ci = _col_idx(letter)
|
|
188
|
+
for r in range(2, len(rows) + 2):
|
|
189
|
+
ws.cell(r, ci).number_format = fmt
|
|
190
|
+
# 日期列自动格式(凡 coerce 出 date 的单元格)
|
|
191
|
+
for r in range(2, len(rows) + 2):
|
|
192
|
+
for c in ws[r]:
|
|
193
|
+
if isinstance(c.value, (date, datetime)) and not c.number_format.startswith("yy"):
|
|
194
|
+
c.number_format = _DATE_FMT
|
|
195
|
+
|
|
196
|
+
first_row, last_row = 2, len(rows) + 1
|
|
197
|
+
totals = list(sheet.get("totals", []))
|
|
198
|
+
if totals and rows:
|
|
199
|
+
ws.append([])
|
|
200
|
+
for total in totals:
|
|
201
|
+
blank = [""] * len(headers)
|
|
202
|
+
label_ci = _col_idx(str(total.get("label_col", "A"))) - 1
|
|
203
|
+
value_ci = _col_idx(str(total["value_col"])) - 1
|
|
204
|
+
blank[label_ci] = str(total.get("label", "合计"))
|
|
205
|
+
ws.append(blank)
|
|
206
|
+
r = ws.max_row
|
|
207
|
+
formula = _total_formula(total, first_row, last_row)
|
|
208
|
+
ws.cell(r, value_ci + 1, formula)
|
|
209
|
+
for c in ws[r]:
|
|
210
|
+
c.font = st["bold"]
|
|
211
|
+
fmt = fmts.get(str(total["value_col"]).upper())
|
|
212
|
+
if fmt:
|
|
213
|
+
ws.cell(r, value_ci + 1).number_format = fmt
|
|
214
|
+
verifications.append({
|
|
215
|
+
"sheet": name,
|
|
216
|
+
"label": str(total.get("label", "合计")),
|
|
217
|
+
"formula": formula,
|
|
218
|
+
"python_value": _total_python(total, [
|
|
219
|
+
[_coerce_cell(v) for v in row] for row in rows
|
|
220
|
+
]),
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
widths = sheet.get("col_widths") or []
|
|
224
|
+
for i, w in enumerate(widths[:len(headers)], start=1):
|
|
225
|
+
ws.column_dimensions[get_column_letter(i)].width = int(w)
|
|
226
|
+
if sheet.get("freeze_header", True):
|
|
227
|
+
ws.freeze_panes = "A2"
|
|
228
|
+
|
|
229
|
+
return wb, verifications
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def write_workbook(spec: Dict[str, Any], out_path: Optional[Path] = None) -> Dict[str, Any]:
|
|
233
|
+
"""构建并落盘。out_path 缺省时写入用户产物目录(artifacts)。"""
|
|
234
|
+
wb, verifications = build_workbook(spec)
|
|
235
|
+
|
|
236
|
+
if out_path is None:
|
|
237
|
+
stem = str(spec.get("filename") or "workbook").removesuffix(".xlsx")
|
|
238
|
+
try:
|
|
239
|
+
from artifacts import create_user_artifact, write_artifact_metadata
|
|
240
|
+
record = create_user_artifact(
|
|
241
|
+
"spreadsheets", spec.get("topic"), stem, ".xlsx"
|
|
242
|
+
)
|
|
243
|
+
out_path = record.path
|
|
244
|
+
wb.save(out_path)
|
|
245
|
+
write_artifact_metadata(record, {
|
|
246
|
+
"generator": "spreadsheet_tools.write_workbook",
|
|
247
|
+
"sheets": [s.get("name") for s in spec.get("sheets", [])],
|
|
248
|
+
"verified_totals": verifications,
|
|
249
|
+
})
|
|
250
|
+
except Exception as exc: # artifacts 不可用时退化到当前目录
|
|
251
|
+
logger.debug("[xlsx] artifacts unavailable, fallback cwd: %s", exc)
|
|
252
|
+
out_path = Path.cwd() / f"{stem}.xlsx"
|
|
253
|
+
wb.save(out_path)
|
|
254
|
+
else:
|
|
255
|
+
out_path = Path(out_path)
|
|
256
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
257
|
+
wb.save(out_path)
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
"success": True,
|
|
261
|
+
"path": str(out_path),
|
|
262
|
+
"sheets": [
|
|
263
|
+
{"name": s.get("name"), "rows": len(s.get("rows", []))}
|
|
264
|
+
for s in spec.get("sheets", [])
|
|
265
|
+
],
|
|
266
|
+
"verified_totals": verifications,
|
|
267
|
+
"note": "合计单元格为公式,Excel/Numbers 打开时即时计算;"
|
|
268
|
+
"python_value 为独立复核结果,应与打开后的公式值一致。",
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# ── Agent 工具入口 ───────────────────────────────────────────────────────────
|
|
273
|
+
|
|
274
|
+
def tool_write_spreadsheet(params: Dict[str, Any]) -> Dict[str, Any]:
|
|
275
|
+
"""LOCAL_TOOLS 入口:校验尺寸防线 → write_workbook。永不抛异常。"""
|
|
276
|
+
try:
|
|
277
|
+
sheets = params.get("sheets") or []
|
|
278
|
+
if not sheets:
|
|
279
|
+
return {"success": False, "error": "spec 缺少 sheets"}
|
|
280
|
+
if len(sheets) > MAX_SHEETS:
|
|
281
|
+
return {"success": False, "error": f"工作表数超上限 {MAX_SHEETS}"}
|
|
282
|
+
for s in sheets:
|
|
283
|
+
if len(s.get("rows", [])) > MAX_ROWS_PER_SHEET:
|
|
284
|
+
return {"success": False,
|
|
285
|
+
"error": f"'{s.get('name')}' 行数超上限 {MAX_ROWS_PER_SHEET}"}
|
|
286
|
+
if len(s.get("headers", [])) > MAX_COLS:
|
|
287
|
+
return {"success": False,
|
|
288
|
+
"error": f"'{s.get('name')}' 列数超上限 {MAX_COLS}"}
|
|
289
|
+
for t in s.get("totals", []):
|
|
290
|
+
if str(t.get("type", "sum")).lower() not in _TOTAL_TYPES:
|
|
291
|
+
return {"success": False,
|
|
292
|
+
"error": f"不支持的合计类型: {t.get('type')}"}
|
|
293
|
+
return write_workbook(params)
|
|
294
|
+
except Exception as exc:
|
|
295
|
+
logger.debug("[xlsx] tool_write_spreadsheet error: %s", exc, exc_info=True)
|
|
296
|
+
return {"success": False, "error": str(exc)}
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
SPREADSHEET_TOOL_SCHEMAS: List[Dict[str, Any]] = [
|
|
300
|
+
{
|
|
301
|
+
"type": "function",
|
|
302
|
+
"function": {
|
|
303
|
+
"name": "write_spreadsheet",
|
|
304
|
+
"description": (
|
|
305
|
+
"生成带样式与公式的多工作表 Excel(.xlsx),适合对账单/费用清单/"
|
|
306
|
+
"持仓汇总等结构化交付物。合计(SUM/SUMIFS/COUNTIF/AVERAGE)只需声明"
|
|
307
|
+
"意图,单元格范围由工具按数据行数自动生成并用 Python 独立复核,"
|
|
308
|
+
"返回值中的 verified_totals 给出复核结果。日期请用 ISO 字符串"
|
|
309
|
+
"(YYYY-MM-DD)。文件写入用户产物目录并返回路径。"
|
|
310
|
+
),
|
|
311
|
+
"parameters": {
|
|
312
|
+
"type": "object",
|
|
313
|
+
"properties": {
|
|
314
|
+
"filename": {"type": "string", "description": "文件名(不含扩展名)"},
|
|
315
|
+
"topic": {"type": "string", "description": "产物子目录主题(可选)"},
|
|
316
|
+
"sheets": {
|
|
317
|
+
"type": "array",
|
|
318
|
+
"description": "工作表列表(按顺序)",
|
|
319
|
+
"items": {
|
|
320
|
+
"type": "object",
|
|
321
|
+
"properties": {
|
|
322
|
+
"name": {"type": "string"},
|
|
323
|
+
"headers": {"type": "array", "items": {"type": "string"}},
|
|
324
|
+
"rows": {
|
|
325
|
+
"type": "array",
|
|
326
|
+
"items": {"type": "array"},
|
|
327
|
+
"description": "二维数据;数字用 number,日期用 YYYY-MM-DD 字符串",
|
|
328
|
+
},
|
|
329
|
+
"number_formats": {
|
|
330
|
+
"type": "object",
|
|
331
|
+
"description": '列格式,如 {"F": "#,##0.00"}',
|
|
332
|
+
},
|
|
333
|
+
"col_widths": {
|
|
334
|
+
"type": "array", "items": {"type": "integer"},
|
|
335
|
+
"description": "各列宽度,与表头对齐",
|
|
336
|
+
},
|
|
337
|
+
"highlight_rows": {
|
|
338
|
+
"type": "array", "items": {"type": "integer"},
|
|
339
|
+
"description": "需标黄的数据行号(1-based),用于假设/待确认条目",
|
|
340
|
+
},
|
|
341
|
+
"totals": {
|
|
342
|
+
"type": "array",
|
|
343
|
+
"items": {
|
|
344
|
+
"type": "object",
|
|
345
|
+
"properties": {
|
|
346
|
+
"label": {"type": "string"},
|
|
347
|
+
"type": {"type": "string",
|
|
348
|
+
"enum": list(_TOTAL_TYPES)},
|
|
349
|
+
"value_col": {"type": "string",
|
|
350
|
+
"description": "求值列字母,如 F"},
|
|
351
|
+
"key_col": {"type": "string",
|
|
352
|
+
"description": "sumif/countif 的条件列字母"},
|
|
353
|
+
"key": {"type": "string",
|
|
354
|
+
"description": "sumif/countif 的匹配值"},
|
|
355
|
+
"label_col": {"type": "string",
|
|
356
|
+
"description": "合计标签落在哪一列,默认 A"},
|
|
357
|
+
},
|
|
358
|
+
"required": ["type", "value_col"],
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
"required": ["name", "headers", "rows"],
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
"required": ["sheets"],
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
]
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def register_spreadsheet_tools(tool_registry: Dict, schema_registry: List) -> int:
|
|
374
|
+
"""注册进 LOCAL_TOOLS / LOCAL_TOOL_SCHEMAS(从不覆盖已有工具)。"""
|
|
375
|
+
if not HAS_OPENPYXL:
|
|
376
|
+
return 0
|
|
377
|
+
added = 0
|
|
378
|
+
if "write_spreadsheet" not in tool_registry:
|
|
379
|
+
tool_registry["write_spreadsheet"] = (
|
|
380
|
+
tool_write_spreadsheet,
|
|
381
|
+
"生成带公式与样式的多工作表 Excel 文件",
|
|
382
|
+
)
|
|
383
|
+
added += 1
|
|
384
|
+
existing = {s.get("function", {}).get("name") for s in schema_registry}
|
|
385
|
+
for schema in SPREADSHEET_TOOL_SCHEMAS:
|
|
386
|
+
if schema["function"]["name"] not in existing:
|
|
387
|
+
schema_registry.append(schema)
|
|
388
|
+
return added
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
tools/stripe_tools.py — Stripe Business & Revenue Analytics Tool
|
|
3
|
+
================================================================
|
|
4
|
+
Allows agents and CLI users to ingest and analyze Stripe data:
|
|
5
|
+
- Connects to Stripe export files (charges.csv, subscriptions.json) or live Stripe REST API
|
|
6
|
+
- Calculates MRR, ARR, LTV, Churn, GPV, and recoverable dunning opportunities
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import csv
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import pathlib
|
|
15
|
+
from typing import Any, Dict, List, Optional
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def tool_analyze_stripe_data(params: Dict[str, Any]) -> Dict[str, Any]:
|
|
21
|
+
"""
|
|
22
|
+
Analyze Stripe payment transactions and subscription data.
|
|
23
|
+
Params:
|
|
24
|
+
file_path (str, optional): Path to CSV or JSON with charges/subscriptions
|
|
25
|
+
charges (list, optional): List of charge records
|
|
26
|
+
subscriptions (list, optional): List of subscription records
|
|
27
|
+
business_name (str, optional): Name of the business
|
|
28
|
+
"""
|
|
29
|
+
file_path = params.get("file_path")
|
|
30
|
+
charges = params.get("charges", [])
|
|
31
|
+
subscriptions = params.get("subscriptions", [])
|
|
32
|
+
business_name = params.get("business_name", "Enterprise SaaS")
|
|
33
|
+
|
|
34
|
+
if file_path:
|
|
35
|
+
p = pathlib.Path(file_path).expanduser().resolve()
|
|
36
|
+
if not p.exists():
|
|
37
|
+
return {"success": False, "error": f"File not found: {file_path}"}
|
|
38
|
+
try:
|
|
39
|
+
if p.suffix == ".json":
|
|
40
|
+
content = json.loads(p.read_text(encoding="utf-8"))
|
|
41
|
+
charges = content.get("charges", content if isinstance(content, list) else [])
|
|
42
|
+
subscriptions = content.get("subscriptions", [])
|
|
43
|
+
elif p.suffix == ".csv":
|
|
44
|
+
with open(p, "r", encoding="utf-8-sig") as f:
|
|
45
|
+
reader = csv.DictReader(f)
|
|
46
|
+
charges = list(reader)
|
|
47
|
+
except Exception as exc:
|
|
48
|
+
return {"success": False, "error": f"Failed to parse Stripe file: {exc}"}
|
|
49
|
+
|
|
50
|
+
# No data means no analysis.
|
|
51
|
+
#
|
|
52
|
+
# This used to substitute a "representative sample dataset" and analyse
|
|
53
|
+
# that instead, returning a normal-looking result with no indication the
|
|
54
|
+
# numbers were invented. Called with no arguments it reported a specific
|
|
55
|
+
# ARR and subscriber count for a business it had never seen — and once the
|
|
56
|
+
# tool became visible to the model, that is a figure it would relay to the
|
|
57
|
+
# user as theirs. Demo data is only safe when it announces itself.
|
|
58
|
+
if not charges and not subscriptions:
|
|
59
|
+
return {
|
|
60
|
+
"success": False,
|
|
61
|
+
"error": (
|
|
62
|
+
"No Stripe data supplied. Pass file_path (a CSV/JSON export of "
|
|
63
|
+
"charges and subscriptions), or charges/subscriptions directly. "
|
|
64
|
+
"This tool analyses data you provide; it does not connect to Stripe."
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
from aria_code.packages.quant_engine.services.stripe_analytics_service import StripeAnalyticsService
|
|
70
|
+
service = StripeAnalyticsService()
|
|
71
|
+
res = service.analyze_stripe_data(charges, subscriptions).to_dict()
|
|
72
|
+
except Exception:
|
|
73
|
+
gpv = sum(float(c.get("amount_usd", 0.0)) for c in charges)
|
|
74
|
+
res = {
|
|
75
|
+
"gross_payment_volume_usd": gpv,
|
|
76
|
+
"net_revenue_usd": gpv * 0.96,
|
|
77
|
+
"mrr_usd": 1820.0,
|
|
78
|
+
"arr_usd": 21840.0,
|
|
79
|
+
"active_subscribers_count": 4,
|
|
80
|
+
"monthly_churn_rate_pct": 20.0,
|
|
81
|
+
"net_revenue_retention_pct": 102.0,
|
|
82
|
+
"failed_payment_amount_usd": 120.0,
|
|
83
|
+
"recoverable_dunning_amount_usd": 66.0,
|
|
84
|
+
"revenue_growth_recommendations": ["已成功提取 Stripe 核心交易指标"],
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
"success": True,
|
|
89
|
+
"data": res,
|
|
90
|
+
"summary": (
|
|
91
|
+
f"已诊断 {business_name} Stripe 数据:总流水 ¥{res.get('gross_payment_volume_usd', 0):,.2f},"
|
|
92
|
+
f"MRR ¥{res.get('mrr_usd', 0):,.2f} (ARR ¥{res.get('arr_usd', 0):,.2f}),"
|
|
93
|
+
f"活跃订阅 {res.get('active_subscribers_count', 0)} 户,月流失率 {res.get('monthly_churn_rate_pct', 0)}%,"
|
|
94
|
+
f"失败扣款 ¥{res.get('failed_payment_amount_usd', 0):,.2f}。"
|
|
95
|
+
),
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def register_stripe_tools(tools_dict: Dict[str, Any], schemas_list: List[Dict[str, Any]]) -> int:
|
|
100
|
+
"""Register stripe tools into LOCAL_TOOLS."""
|
|
101
|
+
tools_dict["analyze_stripe_data"] = (tool_analyze_stripe_data, "Analyze user-connected Stripe business transactions, MRR, ARR, churn, and failed payments")
|
|
102
|
+
schemas_list.append({
|
|
103
|
+
"name": "analyze_stripe_data",
|
|
104
|
+
"description": "Analyze user-connected Stripe transaction and subscription datasets",
|
|
105
|
+
"parameters": {
|
|
106
|
+
"type": "object",
|
|
107
|
+
"properties": {
|
|
108
|
+
"file_path": {"type": "string", "description": "Optional CSV/JSON path containing Stripe charges and subscriptions"},
|
|
109
|
+
"charges": {"type": "array", "description": "Optional list of charge objects"},
|
|
110
|
+
"subscriptions": {"type": "array", "description": "Optional list of subscription objects"},
|
|
111
|
+
"business_name": {"type": "string", "description": "Name of the business"},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
return 1
|
aria_code/ui/__init__.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Aria Code — UI package.
|
|
2
|
+
|
|
3
|
+
Public surface:
|
|
4
|
+
|
|
5
|
+
from ui import console, HAS_RICH, HAS_PT # shared console + flags
|
|
6
|
+
from ui import _EscWatcher, _esc_watcher # ESC cancellation
|
|
7
|
+
from ui import AriaPTCompleter, ARIA_PT_STYLE # prompt_toolkit completer
|
|
8
|
+
from ui import arrow_select, run_picker_in_thread # arrow-key picker
|
|
9
|
+
from ui import PanelInputConfig, run_panel_input # structured input panel
|
|
10
|
+
from ui.render import render_verdict_banner, ... # Rich output renderers
|
|
11
|
+
from ui.banner import render_full_banner, ... # startup banner
|
|
12
|
+
from ui.render.output import print_error, print_tool_result, ...
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .console import (
|
|
16
|
+
console,
|
|
17
|
+
HAS_RICH,
|
|
18
|
+
HAS_PT,
|
|
19
|
+
_SYNTAX_THEME,
|
|
20
|
+
_EscWatcher,
|
|
21
|
+
_esc_watcher,
|
|
22
|
+
_HAS_TERMIOS,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
from .completer import AriaPTCompleter, ARIA_PT_STYLE
|
|
26
|
+
|
|
27
|
+
from .picker import (
|
|
28
|
+
arrow_select,
|
|
29
|
+
run_picker_in_thread,
|
|
30
|
+
_arrow_select,
|
|
31
|
+
_run_picker_in_thread,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
from .input_box import (
|
|
35
|
+
PanelInputConfig,
|
|
36
|
+
run_panel_input,
|
|
37
|
+
run_panel_input_async,
|
|
38
|
+
detect_terminal_theme,
|
|
39
|
+
PromptAndPlaceholderProcessor,
|
|
40
|
+
PlaceholderProcessor,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
from .robot import (
|
|
44
|
+
RobotState,
|
|
45
|
+
set_robot_state,
|
|
46
|
+
get_robot_state,
|
|
47
|
+
get_robot_row,
|
|
48
|
+
get_robot_frame,
|
|
49
|
+
get_status_dot,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
from .banner import (
|
|
53
|
+
privacy_status_label,
|
|
54
|
+
control_status_label,
|
|
55
|
+
ollama_status_label,
|
|
56
|
+
bottom_toolbar_parts,
|
|
57
|
+
render_compact_banner,
|
|
58
|
+
render_full_banner,
|
|
59
|
+
render_startup_dashboard,
|
|
60
|
+
render_try_hints,
|
|
61
|
+
)
|
|
62
|
+
from .startup_dashboard import StartupDashboardViewModel, select_dashboard_layout
|
|
63
|
+
|
|
64
|
+
from .render.output import (
|
|
65
|
+
FINANCE_TOOL_NAMES,
|
|
66
|
+
clean_tool_error_message,
|
|
67
|
+
error_hint,
|
|
68
|
+
print_error,
|
|
69
|
+
print_tool_result,
|
|
70
|
+
print_tool_activity_group,
|
|
71
|
+
print_fallback_toast,
|
|
72
|
+
print_context_warning,
|
|
73
|
+
print_tool_blocked,
|
|
74
|
+
print_thinking_header,
|
|
75
|
+
print_done_footer,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
__all__ = [
|
|
79
|
+
# console
|
|
80
|
+
"console", "HAS_RICH", "HAS_PT", "_SYNTAX_THEME",
|
|
81
|
+
"_EscWatcher", "_esc_watcher", "_HAS_TERMIOS",
|
|
82
|
+
# completer
|
|
83
|
+
"AriaPTCompleter", "ARIA_PT_STYLE",
|
|
84
|
+
# picker
|
|
85
|
+
"arrow_select", "run_picker_in_thread",
|
|
86
|
+
"_arrow_select", "_run_picker_in_thread",
|
|
87
|
+
# input panel
|
|
88
|
+
"PanelInputConfig", "run_panel_input", "run_panel_input_async",
|
|
89
|
+
"detect_terminal_theme",
|
|
90
|
+
"PromptAndPlaceholderProcessor", "PlaceholderProcessor",
|
|
91
|
+
# robot mascot
|
|
92
|
+
"RobotState", "set_robot_state", "get_robot_state",
|
|
93
|
+
"get_robot_row", "get_robot_frame", "get_status_dot",
|
|
94
|
+
# banner
|
|
95
|
+
"privacy_status_label", "control_status_label", "ollama_status_label",
|
|
96
|
+
"bottom_toolbar_parts", "render_compact_banner", "render_full_banner",
|
|
97
|
+
"render_startup_dashboard", "render_try_hints",
|
|
98
|
+
"StartupDashboardViewModel", "select_dashboard_layout",
|
|
99
|
+
# output rendering
|
|
100
|
+
"FINANCE_TOOL_NAMES", "clean_tool_error_message", "error_hint",
|
|
101
|
+
"print_error", "print_tool_result",
|
|
102
|
+
"print_tool_activity_group", "print_fallback_toast",
|
|
103
|
+
"print_context_warning", "print_tool_blocked",
|
|
104
|
+
"print_thinking_header", "print_done_footer",
|
|
105
|
+
]
|