aria-code 0.64.0__tar.gz → 0.66.0__tar.gz
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-0.64.0 → aria_code-0.66.0}/PKG-INFO +1 -1
- {aria_code-0.64.0 → aria_code-0.66.0}/pyproject.toml +1 -1
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/_version.py +1 -1
- aria_code-0.66.0/src/aria_code/apps/channels/README.md +86 -0
- aria_code-0.66.0/src/aria_code/apps/channels/approvals.py +263 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/channels/conversation.py +6 -0
- aria_code-0.66.0/src/aria_code/apps/channels/digest.py +186 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aria_daemon.py +33 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aria_feishu_bot.py +156 -5
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code.egg-info/PKG-INFO +1 -1
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code.egg-info/SOURCES.txt +4 -0
- aria_code-0.66.0/tests/test_card_approvals.py +289 -0
- aria_code-0.66.0/tests/test_shipper_digest.py +241 -0
- aria_code-0.64.0/src/aria_code/apps/channels/README.md +0 -47
- {aria_code-0.64.0 → aria_code-0.66.0}/LICENSE +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/NOTICE +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/README.md +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/setup.cfg +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/adk_apps/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/adk_apps/aria_code_review/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/adk_apps/aria_code_review/agent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/adk_apps/aria_research/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/adk_apps/aria_research/agent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/base.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/code_review.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/calibration_loop.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/critic.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/deepen.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/models.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/pipeline.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/quant_fusion.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/themes.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/deep/tiers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/engineering/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/engineering/coder.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/engineering/tester.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/cashflow_burn.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/catalyst.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/corporate_finance.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/debate.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/earnings.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/fundamental.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/macro.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/news.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/risk.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/sector.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/strategist.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/stripe_revenue.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/synthesis.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/financial/technical.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/orchestrator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/portfolio_agent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/asset_diagnosis.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/business_match.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/cashflow_verify.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/contract_rules.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/energy_anomaly.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/exit_settlement.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/fulfillment_risk.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/ops_optimize.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/realty/revenue_share.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/signal_scheme.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/sports/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/sports/football_agent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/supervisor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/team.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/contracts.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/dashboard.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/fulfillment_leadtime.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/inbound_exceptions.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/inventory_health.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/local_run.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/local_snapshot.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/logistics_cost.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/logistics_sync.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/agents/warehouse/workflow.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aliyun_data_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/README.md +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/channels/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/channels/intake.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/channels/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/channels/tradingview.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/README.md +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/_optional.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/bootstrap.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/broker_render.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/codegen_paths.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/_business_render.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/_ui.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/analysis_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/ashare_prediction_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/auth_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/backtest_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/broker_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/business_workflow_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/canvas_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/catalog.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/core_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/data_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/diagnostic_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/diagnostic_ops_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/file_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/finance_service_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/fx_commodity_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/market.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/market_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/market_context.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/market_render.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/model_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/ops_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/orchestrator_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/pdf_export_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/portfolio_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/scaffold_templates.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/session_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/session_ux_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/team.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/team_render.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/ui_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/warehouse_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/workflow_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/commands/workspace_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/config_paths.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/config_store.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/constants.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/context.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/deterministic.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/direct.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/finance_service_catalog.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/football_reports.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/github_app_auth.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/google_login.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/handlers/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/handlers/broker_handlers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/handlers/chart_handlers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/handlers/market_handlers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/handlers/realty_handlers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/handlers/sports_handlers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/handlers/strategy_advice.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/helpers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/hooks.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/i18n.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/intent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/intent_router.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/intent_signals.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/lifecycle_hooks.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/local_tool_schemas.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/main.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/market_metadata.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/market_universe.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/message_processing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/model_catalog.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/pdf_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/plan_mode.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/plotly_html.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/prediction_feedback.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/preflight.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/project_aria.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/prompt_assembly.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/prompts/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/prompts/coding.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/prompts/select.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/prompts/system_prompts.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/prompts/ui.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/provider_endpoints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/provider_keys.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/base.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/chat_routing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/collaboration.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/llm/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/llm/offline_responses.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/llm/ollama_stream.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/llm/response_cache.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/llm/sse_stream.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/runtime_bridge.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/providers/vertexai_stream.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/runtime_consumer.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/sandbox.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/session_export.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/session_jsonl.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/session_store.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/skills_catalog.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/todo_tracker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tool_executor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tool_registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tool_scope.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tools/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tools/context.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tools/file_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tools/market_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tools/notebook_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tools/system_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tools/write_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/tradingview_bridge.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/turn_planning.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/update_check.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/utils/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/cli/utils/market_detect.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/daemon/README.md +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/vscode/README.md +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/apps/vscode/package.json +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aria_cli.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aria_mcp_server.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aria_relay_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aria_relay_server.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/aria_telegram_bot.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ariarc.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/artifacts.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/backtest_engine.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/backtest_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/automation.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/base.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/capabilities.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/cn/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/cn/easytrader_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/cn/futu_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/cn/longbridge_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/cn/tiger_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/cn/xtquant_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/config.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/intl/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/intl/alpaca_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/intl/ibkr_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/intl/trading212_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/intl/webull_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/paper_broker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/planning.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/brokers/trading.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/canva_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/change_store.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/aliyun_data_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/aria_relay_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/canva_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/figma_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/football_data_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/kling_video_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/market_data_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/openai_image_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/runway_video_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/clients/warehouse_erp_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/cloud_memory.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/command_safety.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/computer_use_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/dashboard_generator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/data_analysis_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/data_cleaner.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/data_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/base.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/router.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/akshare_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/alpha_vantage_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/edgar_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/finnhub_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/fred_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/tushare_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/web_scraper_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/world_bank_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/datasources/sources/yfinance_source.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/demo_player.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/doctor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/domain/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/domain/backtest_engine.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/domain/backtest_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/domain/finance_formulas.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/domain/portfolio_ledger.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/domain/strategy_vault.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/evals/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/evals/harness.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/evals/runner.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/external_agent_runner.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/figma_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/file_analysis_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/finance_formulas.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/football_data_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/image_gen_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/intent_classifier.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/kling_video_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/licensing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/local_finance_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/local_image_provider.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/local_llm_provider.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/macro_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/markdown_pdf.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/market_data_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/mcp_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/memory_manager.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/model_capability.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/notification_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/openai_image_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/adk_bridge/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/adk_bridge/code_review_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/adk_bridge/market_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_agents/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_agents/manifest.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_core/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_core/architecture.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_core/export.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_core/manifest.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_core/paths.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_core/secure_file.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_infra/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_infra/arthera.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_infra/doctor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_infra/product.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_mcp/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_mcp/bridge.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_mcp/circuit.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_mcp/config.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_mcp/installer.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_mcp/server.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_mcp/tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_sdk/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_sdk/client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_sdk/providers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_sdk/streaming.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_sdk/types.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/cache.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/context.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/context_checkpoints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/data.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/provider_health.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/references.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/research_protocol.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/research_quality.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/settings.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_services/usage.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_skills/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_skills/catalog.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_skills/loader.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_skills/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/financial/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/financial/_paths.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/financial/compliance.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/financial/factors.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/financial/risk_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/financial/strategy.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/aria_tools/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/_namespace.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/backtest/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/backtest/core.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/backtest/engine.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/portfolio/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/portfolio/optimizer.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/calibrator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/dixon_coles.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/elo.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/form.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/h2h.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/ml_model.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/predictor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/sports/tracker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/stochastic/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/stochastic/ito_calculus.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/stochastic/kelly_criterion.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/stochastic/options_pricing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packages/quant_engine/stochastic/stochastic_processes.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/base.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/finance/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/logistics/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/payments/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/realty/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/packs/rules.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/plan_utils.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/plugin_loader.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/portfolio_ledger.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/preview_server.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/privacy/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/privacy/feedback.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/project_review.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/project_review_api.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/project_review_server.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/project_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/anthropic.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/autoconfig.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/base.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/custom.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/ollama.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/openai_compat.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/llm/registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/local_image_provider.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/providers/local_llm_provider.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/realty_data_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/report_exporters.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/report_generator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/acceptance.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/agent_loop.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/approval.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/budget.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/checkpoints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/crash_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/events.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/gateway.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/lsp.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/orchestrator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/repo_map.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/run_state.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/run_store.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/self_healing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/subagent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/task_ledger.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/task_orchestrator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/tool_executor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/tool_policy.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runtime/worktrees.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/runway_video_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/safety/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/safety/permissions.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/safety/service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/setup_wizard.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/spreadsheet_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/strategy_vault.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/artifact_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/broker_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/build_quant_engine.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/code_audit_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/computer_use_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/data_analysis_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/enterprise_finance_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/extended_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/file_analysis_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/image_gen_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/local_finance_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/logistics_carriers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/logistics_inventory.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/logistics_io.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/logistics_tenancy.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/logistics_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/macro_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/notification_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/project_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/realty_data_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/spreadsheet_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/tools/stripe_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/banner.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/completer.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/console.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/image_render.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/input_box.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/picker.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/render/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/render/finance.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/render/market.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/render/output.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/render/responsive.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/render/team.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/robot.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/ui/startup_dashboard.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/utils/vscode_uri.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/video_analysis.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/video_editor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/workspace/__init__.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/workspace/files.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/workspace/verify.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/workspace_changes.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/workspace_context.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/workspace_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code/workspace_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code.egg-info/dependency_links.txt +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code.egg-info/entry_points.txt +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code.egg-info/requires.txt +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/src/aria_code.egg-info/top_level.txt +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_adk_market_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_agent_team_fallback.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_analyze_file_tool.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_architecture_ledger_is_true.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_architecture_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_aria_cli_core.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_aria_mcp_server.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_aria_sdk.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_artifact_publishing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_artifacts_and_reports.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ashare_prediction_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_backtest_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_backtest_engine.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_backtest_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_binary_bundles_runtime_imports.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_broken_akshare_is_optional.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_broker_automation.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_broker_chat_confirm_gate.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_broker_planning.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_broker_safety.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_broker_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_budget.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_business_workflow_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_canva_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_canvas_cmds.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_channel_intake.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_channels.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_chart_handlers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_chat_bots_fail_closed.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_chat_routing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ci_security_workflow.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_cli_app_split.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_cli_bootstrap.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_cli_config_store.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_cli_lifecycle_hooks.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_cli_runtime_consumer.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_cli_tool_executor_module.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_cloud_memory.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_code_audit_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_code_review_agent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_codegen_output.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_coder_tester_self_healing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_coder_tool_safety.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_collaboration.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_command_loggers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_command_safety.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_completions_builder.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_config_paths.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_configured_provider.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_container_entrypoint.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_container_entrypoints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_context_checkpoints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_context_references.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_context_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_conversation_core.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_crash_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_credential_file_permissions.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_custom_providers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_daemon_gateway_config.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_dashboard_generator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_data_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_data_service_imports.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_datasource_routing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_deep_analysis.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_degrades_without_quant_engine.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_dispatcher_pins_match_the_release.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_doctor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_doctor_describes_the_current_install.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_doctor_npm_scope.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_engine_boundary.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_enterprise_tool_honesty.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_env_switch_docs.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_evals_harness.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_extended_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_feishu_swarm_config.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_finance_renderers.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_finance_service_catalog.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_first_run_works.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_football_agent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_football_prediction_output.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_google_cloud_routing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_google_login.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_google_search_provider.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_headless_is_agentic.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_image_gen_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_image_inputs.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_import_graph_budget.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_intent_router.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_intent_signals.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_kling_video_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_lazy_rebind.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_legacy_module_imports.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_license_consistency.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_licensing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_local_image_provider.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_logistics_3pl.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_logistics_and_finance_agents.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_lsp.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_markdown_pdf.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_market_data_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_market_history_inheritance.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_market_history_tool.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_market_symbol_extraction.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_market_universe.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_mcp_circuit.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_mcp_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_model_capability_registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_model_choice_is_the_users.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_model_selection_state.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_native_binary_entrypoints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_native_installer.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_new_modules.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_no_hardcoded_developer_paths.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_no_uncommitted_imports.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ollama_stream_imports.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ollama_stream_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_openai_image_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_operations_suite.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_output_rendering.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_packages_facade.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_packaging_constraints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_packaging_manifest.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_packs_domains.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_pdf_report.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_pick_best_installed_model.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_plan_mode.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_platform_package_assembly.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_platform_packages.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_plotly_html_output.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_portfolio_ledger.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_post_turn_context_decision.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_preflight.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_preview_server.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_privacy_feedback.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_project_aria.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_project_review.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_project_review_api.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_prompt_assembly.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_prompt_selection.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_provider_autoconfig.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_provider_error_messages.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_provider_integration.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_provider_registry.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_public_service_status.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_quant_engine_namespace.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_rebind_contract.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_rebind_namespace_contract.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_relay_event_verification.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_release_chain.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_release_commit_identity.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_release_push_is_atomic.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_release_reaches_the_registries.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_release_verification_waits.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_release_workflow_permissions.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_report_charts.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_report_generator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_research_protocol.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_research_quality.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_responsive_rendering.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_root_module_budget.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_rsi_without_pandas_ta.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_acceptance.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_agent_loop.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_approval.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_bridge.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_bridge_fallback.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_checkpoints.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_gateway.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_repo_map.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_run_store.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_tool_executor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runtime_worktrees.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_runway_video_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_safety_permissions.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_safety_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_safety_service_adoption.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_service_diagnostics_security.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_session_search.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_settings_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_single_import_root.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_skill_agent_binding.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_skill_catalog.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_skill_loader.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_spreadsheet_tools.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_sse_stream_contract.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_startup_dashboard.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_streaming_pipeline.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_stripe_agent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_subagent.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_supervisor_routing.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_system_prompts.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_system_tools_output.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_task_orchestrator.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_team_synthesis.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_tls_trust_store.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_tool_policy.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_tool_scope.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_trading_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_tradingview_bridge.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_turn_planning.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ui_completer_references.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ui_console_theme.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ui_input_box.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_ui_robot_banner.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_verification_hint.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_verification_policy.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_version_consistency.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_version_counter.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_video_analysis.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_video_editor.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_vscode_mcp.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_warehouse_agents.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_warehouse_cli_registration.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_warehouse_erp_client.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_warehouse_workflow.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_wheel_is_installable.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_workspace_changes.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_workspace_context.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_workspace_files.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_workspace_scope.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_workspace_service.py +0 -0
- {aria_code-0.64.0 → aria_code-0.66.0}/tests/test_workspace_verify.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "aria-code"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.66.0"
|
|
8
8
|
description = "AI coding and research workspace with optional finance and connected-domain tools"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Channel Apps
|
|
2
|
+
|
|
3
|
+
Target role: adapters for non-terminal entrypoints.
|
|
4
|
+
|
|
5
|
+
Examples:
|
|
6
|
+
|
|
7
|
+
- relay server/client;
|
|
8
|
+
- Feishu bot;
|
|
9
|
+
- Telegram bot;
|
|
10
|
+
- webhooks;
|
|
11
|
+
- future desktop or browser UI.
|
|
12
|
+
|
|
13
|
+
Each channel should translate inbound messages into gateway requests and render
|
|
14
|
+
gateway responses back to the channel. It should not bypass safety, runtime, or
|
|
15
|
+
artifact policies.
|
|
16
|
+
|
|
17
|
+
## The conversation layer (`conversation.py`)
|
|
18
|
+
|
|
19
|
+
Everything a chat bot decides that does not depend on the platform lives in
|
|
20
|
+
one module, so every channel — Feishu today, Arthera's own bot later — gets
|
|
21
|
+
the same rules from the same code:
|
|
22
|
+
|
|
23
|
+
| Rule | Where |
|
|
24
|
+
|------|-------|
|
|
25
|
+
| In a group, answer only when addressed; in a direct chat, always | `should_respond` |
|
|
26
|
+
| One group = one shipper (货主), bound by an admin with `/owner <id>` | `handle_owner_command`, `ConversationStore` |
|
|
27
|
+
| Admins are per channel: `ARIA_CHANNEL_ADMINS=feishu:ou_x,telegram:42` | `is_admin` |
|
|
28
|
+
| Context is the conversation's own recent messages, never another's; capped at 20 messages and 7 days | `ConversationStore.history` |
|
|
29
|
+
| A bound conversation runs every turn with `ARIA_OWNER_SCOPE`, enforced by the logistics tools themselves | `ChannelTurn.env`, `tools/logistics_tenancy.py` |
|
|
30
|
+
|
|
31
|
+
A new channel is an adapter: turn the platform's event into an
|
|
32
|
+
`InboundMessage`, then
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
if not should_respond(msg):
|
|
36
|
+
return
|
|
37
|
+
reply = handle_owner_command(msg, store) # /owner commands
|
|
38
|
+
if reply is None:
|
|
39
|
+
turn = prepare_turn(msg, store) # context + shipper scope
|
|
40
|
+
reply = await run_model(turn.prompt, history=turn.history, env=turn.env)
|
|
41
|
+
store.record(msg.key, "assistant", reply)
|
|
42
|
+
send(reply)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`aria_feishu_bot.feishu_inbound` is the Feishu version of that first step.
|
|
46
|
+
Conversation keys are `<channel>:<conversation id>`, so the same chat id on
|
|
47
|
+
two platforms is two conversations.
|
|
48
|
+
|
|
49
|
+
## The shipper digest (`digest.py`)
|
|
50
|
+
|
|
51
|
+
The first thing the conversation layer enables that a reply-only bot cannot:
|
|
52
|
+
each group bound to a shipper is sent, unprompted, what needs attention —
|
|
53
|
+
reorders, SKUs with too little history to plan, dead stock, waybills to query,
|
|
54
|
+
and safe carrier switches. `run_digests(store, senders)` walks the bindings and
|
|
55
|
+
hands each digest to that channel's sender, so a new channel registers a
|
|
56
|
+
`(conversation_id, title, body) -> bool` function and gets the digest too.
|
|
57
|
+
|
|
58
|
+
Data comes from the operator's `ARIA_SHIPPER_FEEDS` file, never from chat, and
|
|
59
|
+
is read through the logistics tools under `ARIA_OWNER_SCOPE`, so a shared
|
|
60
|
+
multi-shipper export yields only that shipper's lines. Configuration problems
|
|
61
|
+
go to the log, not the client's group; a day with nothing to report sends
|
|
62
|
+
nothing.
|
|
63
|
+
|
|
64
|
+
## Approvals (`approvals.py`)
|
|
65
|
+
|
|
66
|
+
Bot runs cannot use confirmation-required tools, so a bot that may only
|
|
67
|
+
suggest still leaves someone retyping its suggestion. Approvals are the
|
|
68
|
+
sanctioned way through: the bot stores exactly what it proposes, an
|
|
69
|
+
authorised person presses approve or reject in the chat, and only then does
|
|
70
|
+
the action run — once, under the shipper's scope, with who and when recorded.
|
|
71
|
+
|
|
72
|
+
| Rule | Why |
|
|
73
|
+
|------|-----|
|
|
74
|
+
| Approvers per channel (`ARIA_CHANNEL_APPROVERS`, plus admins); none by default | fail closed |
|
|
75
|
+
| Only in the conversation that raised it | a forwarded card cannot be approved elsewhere |
|
|
76
|
+
| A single conditional UPDATE claims the request | two presses cannot both execute |
|
|
77
|
+
| Expires after 24 h | stale numbers should be recomputed, not approved |
|
|
78
|
+
| The conversation must still be bound to the same shipper | a rebound group cannot run the old client's action |
|
|
79
|
+
| The payload is frozen at request time | what was approved is what runs |
|
|
80
|
+
| Failures are recorded, not shown in the chat | exceptions can name host paths |
|
|
81
|
+
|
|
82
|
+
A channel renders the request with two buttons and calls
|
|
83
|
+
`ApprovalStore.decide`; actions are registered in `EXECUTORS`. The first,
|
|
84
|
+
`purchase_order_draft`, writes a CSV to `ARIA_APPROVAL_OUTBOX/<shipper>/` for
|
|
85
|
+
the 3PL's purchasing system: Aria has no integration that places orders, and
|
|
86
|
+
does not pretend to.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"""Approvals: a bot may propose an action with consequences, a person decides.
|
|
2
|
+
|
|
3
|
+
Bot runs cannot use confirmation-required tools, because nobody in a chat can
|
|
4
|
+
answer a terminal prompt. That stops harm and also stops the useful half of
|
|
5
|
+
the job — a reorder list someone still has to retype. This is the other way
|
|
6
|
+
through: the bot writes down exactly what it proposes, an authorised person
|
|
7
|
+
approves or rejects it in the chat, and only then does it happen, with a
|
|
8
|
+
record of who decided what and when.
|
|
9
|
+
|
|
10
|
+
Platform-neutral like the rest of apps/channels. A channel renders a request
|
|
11
|
+
with approve/reject buttons and calls `decide` when one is pressed; the rules
|
|
12
|
+
below hold whichever platform the button was on:
|
|
13
|
+
|
|
14
|
+
- Who may decide: ARIA_CHANNEL_APPROVERS, plus ARIA_CHANNEL_ADMINS, per
|
|
15
|
+
channel ("feishu:ou_x"). Nobody, when neither is set.
|
|
16
|
+
- Where: only in the conversation the request was raised in. A card
|
|
17
|
+
forwarded to another chat cannot be approved there.
|
|
18
|
+
- Once: the transition out of "pending" is a single conditional UPDATE, so
|
|
19
|
+
two clicks, or two approvers at the same moment, cannot both execute.
|
|
20
|
+
- Not late: a request expires after `ttl_seconds` (24 h).
|
|
21
|
+
- Not for someone else: the conversation must still be bound to the shipper
|
|
22
|
+
the request was made for, and the action runs under ARIA_OWNER_SCOPE.
|
|
23
|
+
- What was approved is what runs: the payload is frozen at request time and
|
|
24
|
+
executed as stored, never recomputed — the approver saw these lines.
|
|
25
|
+
|
|
26
|
+
Actions are registered in EXECUTORS. The first, "purchase_order_draft", writes
|
|
27
|
+
a CSV draft to an outbox directory (ARIA_APPROVAL_OUTBOX) for the 3PL's own
|
|
28
|
+
purchasing system to pick up. Aria does not place orders: it has no
|
|
29
|
+
integration that could, and pretending otherwise would be the wrong default.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import csv
|
|
35
|
+
import json
|
|
36
|
+
import os
|
|
37
|
+
import secrets
|
|
38
|
+
import sqlite3
|
|
39
|
+
import time
|
|
40
|
+
from contextlib import contextmanager
|
|
41
|
+
from dataclasses import dataclass
|
|
42
|
+
from pathlib import Path
|
|
43
|
+
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple
|
|
44
|
+
|
|
45
|
+
from aria_code.apps.channels.conversation import ADMINS_ENV, default_db_path
|
|
46
|
+
from aria_code.tools.logistics_tenancy import OWNER_SCOPE_ENV
|
|
47
|
+
|
|
48
|
+
APPROVERS_ENV = "ARIA_CHANNEL_APPROVERS"
|
|
49
|
+
OUTBOX_ENV = "ARIA_APPROVAL_OUTBOX"
|
|
50
|
+
|
|
51
|
+
PENDING, APPROVED, REJECTED, EXPIRED, FAILED = "pending", "approved", "rejected", "expired", "failed"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def can_decide(channel: str, sender_ids: Tuple[str, ...], env: Optional[Dict[str, str]] = None) -> bool:
|
|
55
|
+
env = env if env is not None else os.environ
|
|
56
|
+
allowed = set()
|
|
57
|
+
for key in (APPROVERS_ENV, ADMINS_ENV):
|
|
58
|
+
allowed |= {item.strip() for item in env.get(key, "").split(",") if item.strip()}
|
|
59
|
+
return any(f"{channel}:{sid}" in allowed for sid in sender_ids if sid)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(frozen=True)
|
|
63
|
+
class Approval:
|
|
64
|
+
id: str
|
|
65
|
+
conversation: str
|
|
66
|
+
owner_id: str
|
|
67
|
+
kind: str
|
|
68
|
+
payload: Dict[str, Any]
|
|
69
|
+
summary: str
|
|
70
|
+
requested_by: str
|
|
71
|
+
requested_at: float
|
|
72
|
+
status: str
|
|
73
|
+
decided_by: str = ""
|
|
74
|
+
decided_at: float = 0.0
|
|
75
|
+
result: str = ""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(frozen=True)
|
|
79
|
+
class Decision:
|
|
80
|
+
ok: bool
|
|
81
|
+
message: str
|
|
82
|
+
approval: Optional[Approval] = None
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@contextmanager
|
|
86
|
+
def _confined_to(owner_id: str) -> Iterator[None]:
|
|
87
|
+
previous = os.environ.get(OWNER_SCOPE_ENV)
|
|
88
|
+
os.environ[OWNER_SCOPE_ENV] = owner_id
|
|
89
|
+
try:
|
|
90
|
+
yield
|
|
91
|
+
finally:
|
|
92
|
+
if previous is None:
|
|
93
|
+
os.environ.pop(OWNER_SCOPE_ENV, None)
|
|
94
|
+
else:
|
|
95
|
+
os.environ[OWNER_SCOPE_ENV] = previous
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# ── Executors ────────────────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
def outbox_dir() -> Path:
|
|
101
|
+
configured = os.environ.get(OUTBOX_ENV, "").strip()
|
|
102
|
+
return Path(configured).expanduser() if configured else Path.home() / ".aria" / "outbox"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def execute_purchase_order_draft(approval: Approval) -> str:
|
|
106
|
+
"""Write the approved lines, exactly as approved, as a CSV draft."""
|
|
107
|
+
lines = approval.payload.get("lines") or []
|
|
108
|
+
if not lines:
|
|
109
|
+
raise ValueError("nothing to order")
|
|
110
|
+
folder = outbox_dir() / approval.owner_id
|
|
111
|
+
folder.mkdir(parents=True, exist_ok=True)
|
|
112
|
+
os.chmod(folder, 0o700)
|
|
113
|
+
stamp = time.strftime("%Y%m%d", time.localtime(approval.decided_at or time.time()))
|
|
114
|
+
path = folder / f"PO-{approval.owner_id}-{stamp}-{approval.id[:8]}.csv"
|
|
115
|
+
with path.open("x", newline="", encoding="utf-8") as handle: # never overwrite a draft
|
|
116
|
+
writer = csv.writer(handle)
|
|
117
|
+
writer.writerow(["owner_id", "sku", "order_qty", "approval_id", "approved_by", "approved_at"])
|
|
118
|
+
decided = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(approval.decided_at))
|
|
119
|
+
for line in lines:
|
|
120
|
+
writer.writerow([approval.owner_id, line["sku"], line["qty"], approval.id,
|
|
121
|
+
approval.decided_by, decided])
|
|
122
|
+
return str(path)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
EXECUTORS: Dict[str, Callable[[Approval], str]] = {
|
|
126
|
+
"purchase_order_draft": execute_purchase_order_draft,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def propose_reorder(owner_id: str, inventory_path: str) -> Optional[Tuple[str, Dict[str, Any]]]:
|
|
131
|
+
"""A purchase-order draft from the shipper's reorder list, or None if nothing to order."""
|
|
132
|
+
from aria_code.tools.logistics_inventory import tool_plan_inventory_policy
|
|
133
|
+
|
|
134
|
+
with _confined_to(owner_id):
|
|
135
|
+
result = tool_plan_inventory_policy({"file_path": inventory_path})
|
|
136
|
+
if not result.get("success"):
|
|
137
|
+
raise ValueError(result.get("error") or "inventory analysis failed")
|
|
138
|
+
lines = [{"sku": i["sku"], "qty": int(i["suggested_order_qty"])}
|
|
139
|
+
for i in result["data"]["items"]
|
|
140
|
+
if i.get("action") == "reorder" and i.get("suggested_order_qty")]
|
|
141
|
+
if not lines:
|
|
142
|
+
return None
|
|
143
|
+
summary = "\n".join(f"- {line['sku']}:{line['qty']}" for line in lines)
|
|
144
|
+
return summary, {"lines": lines}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# ── Store ────────────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
class ApprovalStore:
|
|
150
|
+
"""Requests and decisions, in the same SQLite file as the conversations."""
|
|
151
|
+
|
|
152
|
+
def __init__(self, path: Optional[Path | str] = None, *, ttl_seconds: float = 24 * 3600,
|
|
153
|
+
clock: Callable[[], float] = time.time) -> None:
|
|
154
|
+
self.path = Path(path) if path else default_db_path()
|
|
155
|
+
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
156
|
+
self.ttl_seconds = float(ttl_seconds)
|
|
157
|
+
self._clock = clock
|
|
158
|
+
with self._db() as db:
|
|
159
|
+
db.execute(
|
|
160
|
+
"""CREATE TABLE IF NOT EXISTS approvals (
|
|
161
|
+
id TEXT PRIMARY KEY, conversation TEXT NOT NULL, owner_id TEXT NOT NULL,
|
|
162
|
+
kind TEXT NOT NULL, payload TEXT NOT NULL, summary TEXT NOT NULL,
|
|
163
|
+
requested_by TEXT NOT NULL, requested_at REAL NOT NULL,
|
|
164
|
+
status TEXT NOT NULL, decided_by TEXT NOT NULL DEFAULT '',
|
|
165
|
+
decided_at REAL NOT NULL DEFAULT 0, result TEXT NOT NULL DEFAULT '')"""
|
|
166
|
+
)
|
|
167
|
+
try:
|
|
168
|
+
os.chmod(self.path, 0o600)
|
|
169
|
+
except OSError:
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
def _db(self) -> sqlite3.Connection:
|
|
173
|
+
return sqlite3.connect(str(self.path))
|
|
174
|
+
|
|
175
|
+
def request(self, *, conversation: str, owner_id: str, kind: str, payload: Dict[str, Any],
|
|
176
|
+
summary: str, requested_by: str) -> Approval:
|
|
177
|
+
if kind not in EXECUTORS:
|
|
178
|
+
raise ValueError(f"unknown action {kind!r}")
|
|
179
|
+
approval_id = secrets.token_urlsafe(12) # unguessable: it travels in a card button
|
|
180
|
+
with self._db() as db:
|
|
181
|
+
db.execute(
|
|
182
|
+
"INSERT INTO approvals (id, conversation, owner_id, kind, payload, summary, "
|
|
183
|
+
"requested_by, requested_at, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
184
|
+
(approval_id, conversation, owner_id, kind, json.dumps(payload, ensure_ascii=False),
|
|
185
|
+
summary, requested_by, self._clock(), PENDING),
|
|
186
|
+
)
|
|
187
|
+
return self.get(approval_id) # type: ignore[return-value]
|
|
188
|
+
|
|
189
|
+
def get(self, approval_id: str) -> Optional[Approval]:
|
|
190
|
+
with self._db() as db:
|
|
191
|
+
row = db.execute(
|
|
192
|
+
"SELECT id, conversation, owner_id, kind, payload, summary, requested_by, requested_at, "
|
|
193
|
+
"status, decided_by, decided_at, result FROM approvals WHERE id = ?", (approval_id,)
|
|
194
|
+
).fetchone()
|
|
195
|
+
if not row:
|
|
196
|
+
return None
|
|
197
|
+
values = list(row)
|
|
198
|
+
values[4] = json.loads(values[4])
|
|
199
|
+
return Approval(*values)
|
|
200
|
+
|
|
201
|
+
def recent(self, conversation: str, limit: int = 5) -> List[Approval]:
|
|
202
|
+
with self._db() as db:
|
|
203
|
+
ids = [r[0] for r in db.execute(
|
|
204
|
+
"SELECT id FROM approvals WHERE conversation = ? ORDER BY requested_at DESC LIMIT ?",
|
|
205
|
+
(conversation, limit))]
|
|
206
|
+
return [a for a in (self.get(i) for i in ids) if a]
|
|
207
|
+
|
|
208
|
+
def _transition(self, approval_id: str, status: str, by: str, result: str = "",
|
|
209
|
+
expect: str = PENDING) -> bool:
|
|
210
|
+
with self._db() as db:
|
|
211
|
+
cursor = db.execute(
|
|
212
|
+
"UPDATE approvals SET status = ?, decided_by = ?, decided_at = ?, result = ? "
|
|
213
|
+
"WHERE id = ? AND status = ?",
|
|
214
|
+
(status, by, self._clock(), result, approval_id, expect),
|
|
215
|
+
)
|
|
216
|
+
return cursor.rowcount == 1
|
|
217
|
+
|
|
218
|
+
def decide(self, approval_id: str, *, conversation: str, current_owner: Optional[str],
|
|
219
|
+
decided_by: str, approve: bool, authorised: bool) -> Decision:
|
|
220
|
+
"""Apply one approve/reject press. Every refusal says why, and changes nothing."""
|
|
221
|
+
approval = self.get(approval_id)
|
|
222
|
+
if approval is None or approval.conversation != conversation:
|
|
223
|
+
# The same answer for "no such request" and "not this chat's": a
|
|
224
|
+
# forwarded card learns nothing about where it came from.
|
|
225
|
+
return Decision(False, "找不到这条审批,或它不属于本会话。")
|
|
226
|
+
if not authorised:
|
|
227
|
+
return Decision(False, "你没有审批权限。", approval)
|
|
228
|
+
if approval.status != PENDING:
|
|
229
|
+
who = f"({approval.decided_by})" if approval.decided_by else ""
|
|
230
|
+
return Decision(False, f"这条审批已经是「{_STATUS_LABEL.get(approval.status, approval.status)}」{who}。", approval)
|
|
231
|
+
if self._clock() - approval.requested_at > self.ttl_seconds:
|
|
232
|
+
self._transition(approval_id, EXPIRED, "system")
|
|
233
|
+
return Decision(False, "这条审批已过期,请重新发起。", self.get(approval_id))
|
|
234
|
+
if current_owner != approval.owner_id:
|
|
235
|
+
return Decision(False, "本会话绑定的货主已变更,这条审批不能再执行。", approval)
|
|
236
|
+
|
|
237
|
+
if not approve:
|
|
238
|
+
if not self._transition(approval_id, REJECTED, decided_by):
|
|
239
|
+
return Decision(False, "这条审批刚刚已被处理。", self.get(approval_id))
|
|
240
|
+
return Decision(True, "已驳回。", self.get(approval_id))
|
|
241
|
+
|
|
242
|
+
# Claim it first; only the press that wins the claim executes.
|
|
243
|
+
if not self._transition(approval_id, APPROVED, decided_by, result="executing"):
|
|
244
|
+
return Decision(False, "这条审批刚刚已被处理。", self.get(approval_id))
|
|
245
|
+
claimed = self.get(approval_id)
|
|
246
|
+
try:
|
|
247
|
+
with _confined_to(approval.owner_id):
|
|
248
|
+
outcome = EXECUTORS[approval.kind](claimed) # type: ignore[arg-type]
|
|
249
|
+
except Exception as exc:
|
|
250
|
+
# The reason is kept in the record for the operator; the chat only
|
|
251
|
+
# learns that it failed, since an exception can name host paths.
|
|
252
|
+
self._transition(approval_id, FAILED, decided_by, result=str(exc)[:500], expect=APPROVED)
|
|
253
|
+
return Decision(False, "已批准,但执行失败,原因已记录。", self.get(approval_id))
|
|
254
|
+
with self._db() as db:
|
|
255
|
+
db.execute("UPDATE approvals SET result = ? WHERE id = ?", (outcome, approval_id))
|
|
256
|
+
return Decision(True, "已批准并执行。", self.get(approval_id))
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
_STATUS_LABEL = {PENDING: "待审批", APPROVED: "已批准", REJECTED: "已驳回", EXPIRED: "已过期", FAILED: "执行失败"}
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def status_label(status: str) -> str:
|
|
263
|
+
return _STATUS_LABEL.get(status, status)
|
|
@@ -192,6 +192,12 @@ class ConversationStore:
|
|
|
192
192
|
with self._db() as db:
|
|
193
193
|
db.execute("DELETE FROM bindings WHERE conversation = ?", (key,))
|
|
194
194
|
|
|
195
|
+
def bindings(self) -> List[Tuple[str, str]]:
|
|
196
|
+
"""Every (conversation key, shipper) binding, for jobs that push to them."""
|
|
197
|
+
with self._db() as db:
|
|
198
|
+
return [tuple(row) for row in db.execute(
|
|
199
|
+
"SELECT conversation, owner_id FROM bindings ORDER BY conversation")]
|
|
200
|
+
|
|
195
201
|
def owner_for(self, key: str) -> Optional[str]:
|
|
196
202
|
with self._db() as db:
|
|
197
203
|
row = db.execute("SELECT owner_id FROM bindings WHERE conversation = ?", (key,)).fetchone()
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""The daily shipper digest: what needs attention, pushed to the shipper's group.
|
|
2
|
+
|
|
3
|
+
A bot that only answers questions waits to be asked about the SKU that ran out
|
|
4
|
+
yesterday. This sends each shipper's group, unprompted, what the 3PL would
|
|
5
|
+
otherwise find out too late: what to reorder, what history is too thin to
|
|
6
|
+
plan from, what stock has stopped moving, which waybills to query with the
|
|
7
|
+
carrier, and where a cheaper carrier is at least as reliable.
|
|
8
|
+
|
|
9
|
+
Platform-neutral like the rest of apps/channels: it walks the conversations
|
|
10
|
+
bound to a shipper (ConversationStore) and hands each digest to that
|
|
11
|
+
channel's sender. Feishu is the first sender; another channel registers one.
|
|
12
|
+
|
|
13
|
+
Where the data comes from is the operator's decision, not the chat's:
|
|
14
|
+
ARIA_SHIPPER_FEEDS names a JSON file mapping each shipper to its exports —
|
|
15
|
+
|
|
16
|
+
{"ACME": {"inventory": "/data/acme/skus.csv", "waybills": "/data/acme/waybills.csv"},
|
|
17
|
+
"*": {"inventory": "/data/wms/all_skus.csv"}}
|
|
18
|
+
|
|
19
|
+
"*" is the fallback for shippers without their own entry, typically one
|
|
20
|
+
multi-shipper export. Letting a chat command set a path would let anyone in
|
|
21
|
+
the group read any CSV on the host.
|
|
22
|
+
|
|
23
|
+
Every number comes from plan_inventory_policy and score_carriers, run with
|
|
24
|
+
ARIA_OWNER_SCOPE set to the shipper — the same tool-level confinement a bound
|
|
25
|
+
conversation gets — so a shared multi-shipper export yields only that
|
|
26
|
+
shipper's lines, and a file without owner_id is refused rather than guessed.
|
|
27
|
+
Digests are built one at a time: the scope is process environment, and the
|
|
28
|
+
tools are synchronous, so nothing else runs while it is set.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import json
|
|
34
|
+
import logging
|
|
35
|
+
import os
|
|
36
|
+
from contextlib import contextmanager
|
|
37
|
+
from dataclasses import dataclass, field
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
from typing import Awaitable, Callable, Dict, Iterator, List, Optional
|
|
40
|
+
|
|
41
|
+
from aria_code.apps.channels.conversation import ConversationStore
|
|
42
|
+
from aria_code.tools.logistics_tenancy import OWNER_SCOPE_ENV
|
|
43
|
+
|
|
44
|
+
logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
FEEDS_ENV = "ARIA_SHIPPER_FEEDS"
|
|
47
|
+
MAX_LINES = 8 # per section; a digest is a prompt to look, not the report
|
|
48
|
+
|
|
49
|
+
# (conversation_id, title, body) -> delivered?
|
|
50
|
+
Sender = Callable[[str, str, str], Awaitable[bool]]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class Digest:
|
|
55
|
+
owner_id: str
|
|
56
|
+
title: str
|
|
57
|
+
body: str = ""
|
|
58
|
+
items: int = 0
|
|
59
|
+
problems: List[str] = field(default_factory=list)
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def worth_sending(self) -> bool:
|
|
63
|
+
return self.items > 0
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def load_feeds(path: Optional[str] = None) -> Dict[str, Dict[str, str]]:
|
|
67
|
+
"""The operator's shipper → export files map; {} when not configured."""
|
|
68
|
+
source = path or os.environ.get(FEEDS_ENV, "").strip()
|
|
69
|
+
if not source:
|
|
70
|
+
return {}
|
|
71
|
+
data = json.loads(Path(source).expanduser().read_text(encoding="utf-8"))
|
|
72
|
+
if not isinstance(data, dict):
|
|
73
|
+
raise ValueError(f"{FEEDS_ENV} must be a JSON object of shipper -> feeds")
|
|
74
|
+
return {str(k): {kind: str(v) for kind, v in (feeds or {}).items()} for k, feeds in data.items()}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def feeds_for(owner_id: str, feeds: Dict[str, Dict[str, str]]) -> Dict[str, str]:
|
|
78
|
+
return feeds.get(owner_id) or feeds.get("*") or {}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@contextmanager
|
|
82
|
+
def _confined_to(owner_id: str) -> Iterator[None]:
|
|
83
|
+
previous = os.environ.get(OWNER_SCOPE_ENV)
|
|
84
|
+
os.environ[OWNER_SCOPE_ENV] = owner_id
|
|
85
|
+
try:
|
|
86
|
+
yield
|
|
87
|
+
finally:
|
|
88
|
+
if previous is None:
|
|
89
|
+
os.environ.pop(OWNER_SCOPE_ENV, None)
|
|
90
|
+
else:
|
|
91
|
+
os.environ[OWNER_SCOPE_ENV] = previous
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _section(title: str, lines: List[str]) -> str:
|
|
95
|
+
shown = lines[:MAX_LINES]
|
|
96
|
+
more = f"\n- …另有 {len(lines) - MAX_LINES} 项" if len(lines) > MAX_LINES else ""
|
|
97
|
+
return f"**{title}({len(lines)})**\n" + "\n".join(f"- {line}" for line in shown) + more
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def build_digest(owner_id: str, feeds: Dict[str, Dict[str, str]]) -> Digest:
|
|
101
|
+
from aria_code.tools.logistics_carriers import tool_score_carriers
|
|
102
|
+
from aria_code.tools.logistics_inventory import tool_plan_inventory_policy
|
|
103
|
+
|
|
104
|
+
digest = Digest(owner_id=owner_id, title=f"📦 {owner_id} 今日库存与运费提醒")
|
|
105
|
+
sources = feeds_for(owner_id, feeds)
|
|
106
|
+
sections: List[str] = []
|
|
107
|
+
|
|
108
|
+
with _confined_to(owner_id):
|
|
109
|
+
if sources.get("inventory"):
|
|
110
|
+
result = tool_plan_inventory_policy({"file_path": sources["inventory"]})
|
|
111
|
+
if result.get("success"):
|
|
112
|
+
items = result["data"]["items"]
|
|
113
|
+
reorder = [i for i in items if i.get("action") == "reorder"]
|
|
114
|
+
thin = [i for i in items if i.get("action") == "insufficient_history"]
|
|
115
|
+
dead = [i for i in items if i.get("movement") == "dead"]
|
|
116
|
+
if reorder:
|
|
117
|
+
sections.append(_section("建议补货", [
|
|
118
|
+
f"{i['sku']}:订 {i['suggested_order_qty']}(现有可用 {i['inventory_position']:g},"
|
|
119
|
+
f"补货点 {i['reorder_point']},约可撑 {i['days_of_cover']} 天)" for i in reorder])
|
|
120
|
+
+ "\n在群里 @Aria 发送 /补货,可发起采购单草稿审批。")
|
|
121
|
+
if thin:
|
|
122
|
+
sections.append(_section("历史不足、未给建议", [
|
|
123
|
+
f"{i['sku']}:仅 {i['history_days']} 天出库记录" for i in thin]))
|
|
124
|
+
if dead:
|
|
125
|
+
sections.append(_section("呆滞库存", [
|
|
126
|
+
f"{i['sku']}:在库 {i['on_hand']:g}" for i in dead]))
|
|
127
|
+
digest.items += len(reorder) + len(thin) + len(dead)
|
|
128
|
+
else:
|
|
129
|
+
digest.problems.append(f"inventory: {result.get('error')}")
|
|
130
|
+
|
|
131
|
+
if sources.get("waybills"):
|
|
132
|
+
result = tool_score_carriers({"file_path": sources["waybills"]})
|
|
133
|
+
if result.get("success"):
|
|
134
|
+
data = result["data"]
|
|
135
|
+
anomalies, savings = data.get("anomalies") or [], data.get("savings") or []
|
|
136
|
+
if anomalies:
|
|
137
|
+
sections.append(_section("运费待核对", [
|
|
138
|
+
f"{a['waybill_no']}({a['carrier']} {a['lane']}):{a['detail']}" for a in anomalies]))
|
|
139
|
+
if savings:
|
|
140
|
+
sections.append(_section("可节省的线路", [
|
|
141
|
+
f"{s['lane']}:{s['from_carrier']} → {s['to_carrier']},"
|
|
142
|
+
f"按近期运量约省 {s['estimated_saving']:g}(准时率不低于现承运商)" for s in savings]))
|
|
143
|
+
digest.items += len(anomalies) + len(savings)
|
|
144
|
+
else:
|
|
145
|
+
digest.problems.append(f"waybills: {result.get('error')}")
|
|
146
|
+
|
|
147
|
+
if not sources:
|
|
148
|
+
digest.problems.append(f"no feeds configured for {owner_id}")
|
|
149
|
+
digest.body = "\n\n".join(sections) + (
|
|
150
|
+
"\n\n建议数量未计入起订量、箱规和供应商条款;运费异常请先与承运商核对再下结论。" if sections else "")
|
|
151
|
+
return digest
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
async def run_digests(store: ConversationStore, senders: Dict[str, Sender],
|
|
155
|
+
feeds: Optional[Dict[str, Dict[str, str]]] = None) -> List[Dict[str, str]]:
|
|
156
|
+
"""Send today's digest to every bound conversation that has something to say.
|
|
157
|
+
|
|
158
|
+
Returns one record per conversation for the log. Problems — a missing
|
|
159
|
+
feed, a file the tenancy check refused — go to the log only: a client's
|
|
160
|
+
group is not where a 3PL's configuration errors belong.
|
|
161
|
+
"""
|
|
162
|
+
feeds = load_feeds() if feeds is None else feeds
|
|
163
|
+
report: List[Dict[str, str]] = []
|
|
164
|
+
built: Dict[str, Digest] = {}
|
|
165
|
+
for conversation, owner_id in store.bindings():
|
|
166
|
+
channel, _, conversation_id = conversation.partition(":")
|
|
167
|
+
send = senders.get(channel)
|
|
168
|
+
if send is None:
|
|
169
|
+
report.append({"conversation": conversation, "status": "no_sender"})
|
|
170
|
+
continue
|
|
171
|
+
if owner_id not in built:
|
|
172
|
+
try:
|
|
173
|
+
built[owner_id] = build_digest(owner_id, feeds)
|
|
174
|
+
except Exception as exc: # one bad feed must not stop the others
|
|
175
|
+
logger.warning("digest for %s failed: %s", owner_id, exc)
|
|
176
|
+
report.append({"conversation": conversation, "status": "error"})
|
|
177
|
+
continue
|
|
178
|
+
digest = built[owner_id]
|
|
179
|
+
for problem in digest.problems:
|
|
180
|
+
logger.warning("digest %s: %s", owner_id, problem)
|
|
181
|
+
if not digest.worth_sending:
|
|
182
|
+
report.append({"conversation": conversation, "status": "nothing_to_report"})
|
|
183
|
+
continue
|
|
184
|
+
delivered = await send(conversation_id, digest.title, digest.body)
|
|
185
|
+
report.append({"conversation": conversation, "status": "sent" if delivered else "send_failed"})
|
|
186
|
+
return report
|
|
@@ -1080,6 +1080,25 @@ async def _execute_job(job: dict) -> None:
|
|
|
1080
1080
|
conn.commit()
|
|
1081
1081
|
|
|
1082
1082
|
|
|
1083
|
+
# ── Shipper digest ───────────────────────────────────────────────────────────
|
|
1084
|
+
|
|
1085
|
+
async def _run_shipper_digests() -> None:
|
|
1086
|
+
"""Push each bound shipper group its digest (apps/channels/digest.py)."""
|
|
1087
|
+
try:
|
|
1088
|
+
from apps.channels.conversation import ConversationStore
|
|
1089
|
+
from apps.channels.digest import run_digests
|
|
1090
|
+
|
|
1091
|
+
senders = {}
|
|
1092
|
+
if os.environ.get("FEISHU_APP_ID") and os.environ.get("FEISHU_APP_SECRET"):
|
|
1093
|
+
from aria_feishu_bot import send_digest_card
|
|
1094
|
+
senders["feishu"] = send_digest_card
|
|
1095
|
+
report = await run_digests(ConversationStore(), senders)
|
|
1096
|
+
for line in report:
|
|
1097
|
+
logger.info("shipper digest %s: %s", line["conversation"], line["status"])
|
|
1098
|
+
except Exception as exc:
|
|
1099
|
+
logger.error("shipper digest job failed: %s", exc)
|
|
1100
|
+
|
|
1101
|
+
|
|
1083
1102
|
# ── APScheduler cron ─────────────────────────────────────────────────────────
|
|
1084
1103
|
|
|
1085
1104
|
def _start_scheduler() -> None:
|
|
@@ -1152,6 +1171,20 @@ def _start_scheduler() -> None:
|
|
|
1152
1171
|
)
|
|
1153
1172
|
logger.info("Registered 4 default scheduled jobs (morning / US / evening / weekly)")
|
|
1154
1173
|
|
|
1174
|
+
# Shipper digest: each group bound to a shipper gets what needs
|
|
1175
|
+
# attention. Only when the operator has said where the data is.
|
|
1176
|
+
if os.environ.get("ARIA_SHIPPER_FEEDS", "").strip():
|
|
1177
|
+
cron = os.environ.get("ARIA_DIGEST_CRON", "30 8 * * 1-6").strip()
|
|
1178
|
+
scheduler.add_job(
|
|
1179
|
+
_run_shipper_digests,
|
|
1180
|
+
CronTrigger.from_crontab(cron, timezone="Asia/Shanghai"),
|
|
1181
|
+
id="default_shipper_digest",
|
|
1182
|
+
name="货主库存与运费提醒",
|
|
1183
|
+
replace_existing=True,
|
|
1184
|
+
misfire_grace_time=1800,
|
|
1185
|
+
)
|
|
1186
|
+
logger.info("Registered shipper digest [%s]", cron)
|
|
1187
|
+
|
|
1155
1188
|
scheduler.start()
|
|
1156
1189
|
logger.info("APScheduler started with %d job(s)", len(scheduler.get_jobs()))
|
|
1157
1190
|
return scheduler
|