aria-code 0.65.0__tar.gz → 0.67.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.65.0 → aria_code-0.67.0}/PKG-INFO +4 -1
- {aria_code-0.65.0 → aria_code-0.67.0}/pyproject.toml +7 -1
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/_version.py +1 -1
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/channels/README.md +35 -0
- aria_code-0.67.0/src/aria_code/apps/channels/approvals.py +263 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/channels/digest.py +2 -1
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aria_daemon.py +5 -3
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aria_feishu_bot.py +158 -45
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aria_relay_server.py +145 -1
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/aria_relay_client.py +44 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code.egg-info/PKG-INFO +4 -1
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code.egg-info/SOURCES.txt +3 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code.egg-info/requires.txt +3 -0
- aria_code-0.67.0/tests/test_card_approvals.py +289 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_project_review_api.py +3 -3
- aria_code-0.67.0/tests/test_relay_sends_for_clients.py +270 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/LICENSE +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/NOTICE +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/README.md +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/setup.cfg +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/adk_apps/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/adk_apps/aria_code_review/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/adk_apps/aria_code_review/agent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/adk_apps/aria_research/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/adk_apps/aria_research/agent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/base.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/code_review.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/calibration_loop.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/critic.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/deepen.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/models.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/pipeline.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/quant_fusion.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/themes.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/deep/tiers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/engineering/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/engineering/coder.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/engineering/tester.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/cashflow_burn.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/catalyst.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/corporate_finance.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/debate.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/earnings.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/fundamental.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/macro.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/news.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/risk.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/sector.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/strategist.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/stripe_revenue.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/synthesis.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/financial/technical.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/orchestrator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/portfolio_agent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/asset_diagnosis.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/business_match.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/cashflow_verify.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/contract_rules.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/energy_anomaly.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/exit_settlement.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/fulfillment_risk.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/ops_optimize.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/realty/revenue_share.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/signal_scheme.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/sports/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/sports/football_agent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/supervisor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/team.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/contracts.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/dashboard.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/fulfillment_leadtime.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/inbound_exceptions.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/inventory_health.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/local_run.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/local_snapshot.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/logistics_cost.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/logistics_sync.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/agents/warehouse/workflow.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aliyun_data_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/README.md +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/channels/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/channels/conversation.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/channels/intake.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/channels/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/channels/tradingview.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/README.md +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/_optional.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/bootstrap.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/broker_render.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/codegen_paths.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/_business_render.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/_ui.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/analysis_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/ashare_prediction_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/auth_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/backtest_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/broker_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/business_workflow_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/canvas_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/catalog.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/core_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/data_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/diagnostic_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/diagnostic_ops_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/file_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/finance_service_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/fx_commodity_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/market.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/market_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/market_context.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/market_render.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/model_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/ops_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/orchestrator_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/pdf_export_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/portfolio_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/scaffold_templates.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/session_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/session_ux_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/team.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/team_render.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/ui_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/warehouse_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/workflow_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/commands/workspace_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/config_paths.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/config_store.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/constants.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/context.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/deterministic.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/direct.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/finance_service_catalog.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/football_reports.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/github_app_auth.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/google_login.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/handlers/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/handlers/broker_handlers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/handlers/chart_handlers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/handlers/market_handlers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/handlers/realty_handlers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/handlers/sports_handlers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/handlers/strategy_advice.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/helpers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/hooks.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/i18n.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/intent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/intent_router.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/intent_signals.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/lifecycle_hooks.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/local_tool_schemas.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/main.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/market_metadata.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/market_universe.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/message_processing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/model_catalog.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/pdf_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/plan_mode.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/plotly_html.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/prediction_feedback.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/preflight.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/project_aria.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/prompt_assembly.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/prompts/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/prompts/coding.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/prompts/select.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/prompts/system_prompts.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/prompts/ui.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/provider_endpoints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/provider_keys.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/base.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/chat_routing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/collaboration.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/llm/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/llm/offline_responses.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/llm/ollama_stream.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/llm/response_cache.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/llm/sse_stream.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/runtime_bridge.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/providers/vertexai_stream.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/runtime_consumer.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/sandbox.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/session_export.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/session_jsonl.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/session_store.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/skills_catalog.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/todo_tracker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tool_executor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tool_registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tool_scope.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tools/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tools/context.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tools/file_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tools/market_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tools/notebook_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tools/system_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tools/write_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/tradingview_bridge.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/turn_planning.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/update_check.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/utils/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/cli/utils/market_detect.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/daemon/README.md +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/vscode/README.md +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/apps/vscode/package.json +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aria_cli.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aria_mcp_server.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aria_relay_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/aria_telegram_bot.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ariarc.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/artifacts.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/backtest_engine.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/backtest_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/automation.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/base.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/capabilities.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/cn/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/cn/easytrader_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/cn/futu_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/cn/longbridge_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/cn/tiger_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/cn/xtquant_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/config.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/intl/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/intl/alpaca_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/intl/ibkr_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/intl/trading212_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/intl/webull_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/paper_broker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/planning.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/brokers/trading.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/canva_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/change_store.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/aliyun_data_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/canva_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/figma_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/football_data_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/kling_video_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/market_data_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/openai_image_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/runway_video_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/clients/warehouse_erp_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/cloud_memory.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/command_safety.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/computer_use_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/dashboard_generator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/data_analysis_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/data_cleaner.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/data_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/base.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/router.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/akshare_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/alpha_vantage_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/edgar_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/finnhub_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/fred_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/tushare_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/web_scraper_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/world_bank_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/datasources/sources/yfinance_source.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/demo_player.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/doctor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/domain/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/domain/backtest_engine.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/domain/backtest_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/domain/finance_formulas.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/domain/portfolio_ledger.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/domain/strategy_vault.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/evals/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/evals/harness.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/evals/runner.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/external_agent_runner.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/figma_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/file_analysis_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/finance_formulas.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/football_data_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/image_gen_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/intent_classifier.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/kling_video_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/licensing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/local_finance_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/local_image_provider.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/local_llm_provider.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/macro_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/markdown_pdf.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/market_data_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/mcp_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/memory_manager.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/model_capability.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/notification_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/openai_image_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/adk_bridge/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/adk_bridge/code_review_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/adk_bridge/market_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_agents/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_agents/manifest.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_core/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_core/architecture.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_core/export.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_core/manifest.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_core/paths.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_core/secure_file.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_infra/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_infra/arthera.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_infra/doctor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_infra/product.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_mcp/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_mcp/bridge.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_mcp/circuit.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_mcp/config.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_mcp/installer.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_mcp/server.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_mcp/tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_sdk/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_sdk/client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_sdk/providers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_sdk/streaming.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_sdk/types.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/cache.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/context.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/context_checkpoints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/data.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/provider_health.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/references.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/research_protocol.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/research_quality.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/settings.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_services/usage.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_skills/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_skills/catalog.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_skills/loader.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_skills/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/financial/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/financial/_paths.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/financial/compliance.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/financial/factors.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/financial/risk_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/financial/strategy.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/aria_tools/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/_namespace.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/backtest/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/backtest/core.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/backtest/engine.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/portfolio/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/portfolio/optimizer.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/calibrator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/dixon_coles.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/elo.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/form.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/h2h.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/ml_model.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/predictor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/sports/tracker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/stochastic/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/stochastic/ito_calculus.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/stochastic/kelly_criterion.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/stochastic/options_pricing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packages/quant_engine/stochastic/stochastic_processes.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/base.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/finance/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/logistics/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/payments/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/realty/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/packs/rules.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/plan_utils.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/plugin_loader.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/portfolio_ledger.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/preview_server.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/privacy/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/privacy/feedback.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/project_review.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/project_review_api.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/project_review_server.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/project_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/anthropic.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/autoconfig.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/base.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/custom.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/ollama.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/openai_compat.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/llm/registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/local_image_provider.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/providers/local_llm_provider.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/realty_data_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/report_exporters.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/report_generator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/acceptance.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/agent_loop.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/approval.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/budget.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/checkpoints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/crash_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/events.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/gateway.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/lsp.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/orchestrator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/repo_map.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/run_state.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/run_store.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/self_healing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/subagent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/task_ledger.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/task_orchestrator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/tool_executor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/tool_policy.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runtime/worktrees.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/runway_video_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/safety/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/safety/permissions.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/safety/service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/setup_wizard.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/spreadsheet_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/strategy_vault.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/artifact_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/broker_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/build_quant_engine.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/code_audit_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/computer_use_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/data_analysis_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/enterprise_finance_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/extended_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/file_analysis_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/image_gen_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/local_finance_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/logistics_carriers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/logistics_inventory.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/logistics_io.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/logistics_tenancy.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/logistics_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/macro_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/notification_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/project_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/realty_data_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/spreadsheet_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/tools/stripe_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/banner.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/completer.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/console.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/image_render.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/input_box.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/picker.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/render/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/render/finance.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/render/market.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/render/output.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/render/responsive.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/render/team.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/robot.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/ui/startup_dashboard.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/utils/vscode_uri.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/video_analysis.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/video_editor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/workspace/__init__.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/workspace/files.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/workspace/verify.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/workspace_changes.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/workspace_context.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/workspace_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code/workspace_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code.egg-info/dependency_links.txt +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code.egg-info/entry_points.txt +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/src/aria_code.egg-info/top_level.txt +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_adk_market_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_agent_team_fallback.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_analyze_file_tool.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_architecture_ledger_is_true.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_architecture_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_aria_cli_core.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_aria_mcp_server.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_aria_sdk.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_artifact_publishing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_artifacts_and_reports.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ashare_prediction_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_backtest_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_backtest_engine.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_backtest_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_binary_bundles_runtime_imports.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_broken_akshare_is_optional.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_broker_automation.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_broker_chat_confirm_gate.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_broker_planning.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_broker_safety.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_broker_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_budget.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_business_workflow_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_canva_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_canvas_cmds.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_channel_intake.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_channels.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_chart_handlers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_chat_bots_fail_closed.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_chat_routing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ci_security_workflow.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_cli_app_split.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_cli_bootstrap.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_cli_config_store.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_cli_lifecycle_hooks.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_cli_runtime_consumer.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_cli_tool_executor_module.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_cloud_memory.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_code_audit_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_code_review_agent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_codegen_output.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_coder_tester_self_healing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_coder_tool_safety.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_collaboration.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_command_loggers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_command_safety.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_completions_builder.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_config_paths.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_configured_provider.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_container_entrypoint.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_container_entrypoints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_context_checkpoints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_context_references.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_context_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_conversation_core.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_crash_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_credential_file_permissions.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_custom_providers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_daemon_gateway_config.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_dashboard_generator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_data_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_data_service_imports.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_datasource_routing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_deep_analysis.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_degrades_without_quant_engine.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_dispatcher_pins_match_the_release.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_doctor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_doctor_describes_the_current_install.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_doctor_npm_scope.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_engine_boundary.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_enterprise_tool_honesty.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_env_switch_docs.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_evals_harness.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_extended_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_feishu_swarm_config.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_finance_renderers.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_finance_service_catalog.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_first_run_works.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_football_agent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_football_prediction_output.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_google_cloud_routing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_google_login.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_google_search_provider.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_headless_is_agentic.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_image_gen_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_image_inputs.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_import_graph_budget.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_intent_router.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_intent_signals.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_kling_video_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_lazy_rebind.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_legacy_module_imports.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_license_consistency.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_licensing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_local_image_provider.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_logistics_3pl.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_logistics_and_finance_agents.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_lsp.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_markdown_pdf.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_market_data_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_market_history_inheritance.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_market_history_tool.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_market_symbol_extraction.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_market_universe.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_mcp_circuit.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_mcp_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_model_capability_registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_model_choice_is_the_users.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_model_selection_state.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_native_binary_entrypoints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_native_installer.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_new_modules.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_no_hardcoded_developer_paths.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_no_uncommitted_imports.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ollama_stream_imports.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ollama_stream_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_openai_image_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_operations_suite.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_output_rendering.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_packages_facade.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_packaging_constraints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_packaging_manifest.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_packs_domains.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_pdf_report.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_pick_best_installed_model.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_plan_mode.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_platform_package_assembly.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_platform_packages.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_plotly_html_output.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_portfolio_ledger.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_post_turn_context_decision.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_preflight.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_preview_server.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_privacy_feedback.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_project_aria.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_project_review.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_prompt_assembly.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_prompt_selection.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_provider_autoconfig.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_provider_error_messages.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_provider_integration.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_provider_registry.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_public_service_status.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_quant_engine_namespace.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_rebind_contract.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_rebind_namespace_contract.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_relay_event_verification.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_release_chain.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_release_commit_identity.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_release_push_is_atomic.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_release_reaches_the_registries.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_release_verification_waits.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_release_workflow_permissions.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_report_charts.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_report_generator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_research_protocol.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_research_quality.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_responsive_rendering.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_root_module_budget.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_rsi_without_pandas_ta.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_acceptance.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_agent_loop.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_approval.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_bridge.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_bridge_fallback.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_checkpoints.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_gateway.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_repo_map.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_run_store.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_tool_executor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runtime_worktrees.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_runway_video_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_safety_permissions.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_safety_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_safety_service_adoption.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_service_diagnostics_security.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_session_search.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_settings_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_shipper_digest.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_single_import_root.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_skill_agent_binding.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_skill_catalog.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_skill_loader.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_spreadsheet_tools.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_sse_stream_contract.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_startup_dashboard.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_streaming_pipeline.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_stripe_agent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_subagent.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_supervisor_routing.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_system_prompts.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_system_tools_output.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_task_orchestrator.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_team_synthesis.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_tls_trust_store.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_tool_policy.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_tool_scope.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_trading_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_tradingview_bridge.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_turn_planning.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ui_completer_references.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ui_console_theme.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ui_input_box.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_ui_robot_banner.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_verification_hint.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_verification_policy.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_version_consistency.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_version_counter.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_video_analysis.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_video_editor.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_vscode_mcp.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_warehouse_agents.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_warehouse_cli_registration.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_warehouse_erp_client.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_warehouse_workflow.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_wheel_is_installable.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_workspace_changes.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_workspace_context.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_workspace_files.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_workspace_scope.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_workspace_service.py +0 -0
- {aria_code-0.65.0 → aria_code-0.67.0}/tests/test_workspace_verify.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aria-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.67.0
|
|
4
4
|
Summary: AI coding and research workspace with optional finance and connected-domain tools
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/artheras/aria-code
|
|
@@ -108,6 +108,9 @@ Requires-Dist: pytest-asyncio>=0.23.7; extra == "dev"
|
|
|
108
108
|
Requires-Dist: pytest-timeout>=2.3.0; extra == "dev"
|
|
109
109
|
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
110
110
|
Requires-Dist: mypy>=1.10.0; extra == "dev"
|
|
111
|
+
Requires-Dist: fastapi>=0.110.0; extra == "dev"
|
|
112
|
+
Requires-Dist: uvicorn>=0.29.0; extra == "dev"
|
|
113
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "dev"
|
|
111
114
|
Provides-Extra: full
|
|
112
115
|
Requires-Dist: google-genai>=1.0.0; extra == "full"
|
|
113
116
|
Requires-Dist: akshare>=1.14.68; extra == "full"
|
|
@@ -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.67.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" }
|
|
@@ -156,6 +156,12 @@ dev = [
|
|
|
156
156
|
"pytest-timeout>=2.3.0",
|
|
157
157
|
"ruff>=0.4.0",
|
|
158
158
|
"mypy>=1.10.0",
|
|
159
|
+
# The relay server's and the project-review service's tests. Without
|
|
160
|
+
# these, importorskip skipped them all in CI — the relay's account-hijack
|
|
161
|
+
# regressions included — and nobody noticed.
|
|
162
|
+
"fastapi>=0.110.0",
|
|
163
|
+
"uvicorn>=0.29.0",
|
|
164
|
+
"python-multipart>=0.0.9",
|
|
159
165
|
]
|
|
160
166
|
|
|
161
167
|
# ── Full feature set (what the bootstrap installers install by default) ────────
|
|
@@ -60,3 +60,38 @@ is read through the logistics tools under `ARIA_OWNER_SCOPE`, so a shared
|
|
|
60
60
|
multi-shipper export yields only that shipper's lines. Configuration problems
|
|
61
61
|
go to the log, not the client's group; a day with nothing to report sends
|
|
62
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.
|
|
87
|
+
|
|
88
|
+
## Relay mode
|
|
89
|
+
|
|
90
|
+
In relay mode the user's machine has no Feishu app credentials — the app
|
|
91
|
+
secret stays on the relay — so `aria_feishu_bot._send_message` hands every
|
|
92
|
+
message back over the relay WebSocket and the relay sends it. The relay
|
|
93
|
+
accepts a send only where the client has standing: a reply to a message it
|
|
94
|
+
forwarded to that client (within an hour), or a post to a chat that client's
|
|
95
|
+
bound user has spoken to the bot in; text or cards, rate-limited. A press on a
|
|
96
|
+
card is routed to the client that posted the card, which holds the approval.
|
|
97
|
+
Attachments still need the app's credentials and are declined with a message.
|
|
@@ -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)
|
|
@@ -116,7 +116,8 @@ def build_digest(owner_id: str, feeds: Dict[str, Dict[str, str]]) -> Digest:
|
|
|
116
116
|
if reorder:
|
|
117
117
|
sections.append(_section("建议补货", [
|
|
118
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])
|
|
119
|
+
f"补货点 {i['reorder_point']},约可撑 {i['days_of_cover']} 天)" for i in reorder])
|
|
120
|
+
+ "\n在群里 @Aria 发送 /补货,可发起采购单草稿审批。")
|
|
120
121
|
if thin:
|
|
121
122
|
sections.append(_section("历史不足、未给建议", [
|
|
122
123
|
f"{i['sku']}:仅 {i['history_days']} 天出库记录" for i in thin]))
|
|
@@ -1089,9 +1089,11 @@ async def _run_shipper_digests() -> None:
|
|
|
1089
1089
|
from apps.channels.digest import run_digests
|
|
1090
1090
|
|
|
1091
1091
|
senders = {}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1092
|
+
import aria_feishu_bot
|
|
1093
|
+
# With the app's credentials (self-hosted), or through the relay client
|
|
1094
|
+
# this daemon runs in relay mode — the bot knows which it has.
|
|
1095
|
+
if aria_feishu_bot.can_send():
|
|
1096
|
+
senders["feishu"] = aria_feishu_bot.send_digest_card
|
|
1095
1097
|
report = await run_digests(ConversationStore(), senders)
|
|
1096
1098
|
for line in report:
|
|
1097
1099
|
logger.info("shipper digest %s: %s", line["conversation"], line["status"])
|
|
@@ -157,6 +157,48 @@ async def _get_access_token() -> Optional[str]:
|
|
|
157
157
|
|
|
158
158
|
# ── Send message helpers ───────────────────────────────────────────────────────
|
|
159
159
|
|
|
160
|
+
# Set by the relay client while it is connected. In relay mode this machine has
|
|
161
|
+
# no Feishu app credentials — by design, the app secret stays on the relay — so
|
|
162
|
+
# every message goes back over the WebSocket and the relay sends it. Before
|
|
163
|
+
# 2026-10-03 nothing did this, and relay mode silently dropped every answer.
|
|
164
|
+
_RELAY_SEND = None
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def set_relay_sender(sender) -> None:
|
|
168
|
+
"""Route sends through the relay: sender(request) -> Feishu-style result dict."""
|
|
169
|
+
global _RELAY_SEND
|
|
170
|
+
_RELAY_SEND = sender
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def can_send() -> bool:
|
|
174
|
+
"""Whether this process can deliver a message at all."""
|
|
175
|
+
has_app = bool(os.environ.get("FEISHU_APP_ID") and os.environ.get("FEISHU_APP_SECRET"))
|
|
176
|
+
return has_app or _RELAY_SEND is not None
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
async def _send_message(op: str, target: str, msg_type: str, content: str,
|
|
180
|
+
receive_id_type: str = "chat_id") -> Optional[dict]:
|
|
181
|
+
"""The one place a message leaves: directly with app credentials, else via the relay.
|
|
182
|
+
|
|
183
|
+
op "reply" answers message `target`; op "send" posts to chat `target`.
|
|
184
|
+
"""
|
|
185
|
+
token = await _get_access_token()
|
|
186
|
+
if token:
|
|
187
|
+
if op == "reply":
|
|
188
|
+
return await _feishu_post(f"{_FEISHU_API}/im/v1/messages/{target}/reply", token,
|
|
189
|
+
{"msg_type": msg_type, "content": content})
|
|
190
|
+
return await _feishu_post(f"{_FEISHU_API}/im/v1/messages?receive_id_type={receive_id_type}",
|
|
191
|
+
token, {"receive_id": target, "msg_type": msg_type, "content": content})
|
|
192
|
+
if _RELAY_SEND is not None:
|
|
193
|
+
try:
|
|
194
|
+
return await _RELAY_SEND({"op": op, "target": target, "msg_type": msg_type,
|
|
195
|
+
"content": content, "receive_id_type": receive_id_type})
|
|
196
|
+
except Exception as exc:
|
|
197
|
+
logger.warning("relay send failed: %s", exc)
|
|
198
|
+
return None
|
|
199
|
+
logger.error("cannot send: no Feishu app credentials and no relay connection")
|
|
200
|
+
return None
|
|
201
|
+
|
|
160
202
|
async def _feishu_post(url: str, token: str, payload: dict) -> Optional[dict]:
|
|
161
203
|
"""POST to Feishu API; log the response code on error."""
|
|
162
204
|
try:
|
|
@@ -187,16 +229,8 @@ async def reply_text(message_id: str, text: str) -> None:
|
|
|
187
229
|
if not message_id:
|
|
188
230
|
logger.error("reply_text: empty message_id — cannot reply")
|
|
189
231
|
return
|
|
190
|
-
token = await _get_access_token()
|
|
191
|
-
if not token:
|
|
192
|
-
logger.error("reply_text: no access token")
|
|
193
|
-
return
|
|
194
232
|
logger.info("reply_text → message_id=%s len=%d", message_id, len(text))
|
|
195
|
-
await
|
|
196
|
-
f"{_FEISHU_API}/im/v1/messages/{message_id}/reply",
|
|
197
|
-
token,
|
|
198
|
-
{"msg_type": "text", "content": json.dumps({"text": text[:3000]})},
|
|
199
|
-
)
|
|
233
|
+
await _send_message("reply", message_id, "text", json.dumps({"text": text[:3000]}))
|
|
200
234
|
|
|
201
235
|
|
|
202
236
|
async def reply_card(message_id: str, title: str, body: str,
|
|
@@ -205,10 +239,6 @@ async def reply_card(message_id: str, title: str, body: str,
|
|
|
205
239
|
if not message_id:
|
|
206
240
|
logger.error("reply_card: empty message_id — cannot reply")
|
|
207
241
|
return
|
|
208
|
-
token = await _get_access_token()
|
|
209
|
-
if not token:
|
|
210
|
-
await reply_text(message_id, f"【{title}】\n{body}")
|
|
211
|
-
return
|
|
212
242
|
elements = _build_card_elements(body, footer)
|
|
213
243
|
card = {
|
|
214
244
|
"config": {"wide_screen_mode": True},
|
|
@@ -216,11 +246,7 @@ async def reply_card(message_id: str, title: str, body: str,
|
|
|
216
246
|
"elements": elements,
|
|
217
247
|
}
|
|
218
248
|
logger.info("reply_card → message_id=%s title=%s", message_id, title[:40])
|
|
219
|
-
result = await
|
|
220
|
-
f"{_FEISHU_API}/im/v1/messages/{message_id}/reply",
|
|
221
|
-
token,
|
|
222
|
-
{"msg_type": "interactive", "content": json.dumps(card)},
|
|
223
|
-
)
|
|
249
|
+
result = await _send_message("reply", message_id, "interactive", json.dumps(card))
|
|
224
250
|
# If card failed, fall back to plain text
|
|
225
251
|
if result and result.get("code") != 0:
|
|
226
252
|
logger.info("reply_card: card failed (code %s), falling back to text", result.get("code"))
|
|
@@ -280,20 +306,13 @@ def _build_card_elements(body: str, footer: str = "") -> list:
|
|
|
280
306
|
async def _reply_card_raw(message_id: str, title: str, body: str,
|
|
281
307
|
color: str = "blue", footer: str = "") -> Optional[dict]:
|
|
282
308
|
"""Reply with a card; return raw API response dict."""
|
|
283
|
-
token = await _get_access_token()
|
|
284
|
-
if not token:
|
|
285
|
-
return None
|
|
286
309
|
elements = _build_card_elements(body, footer)
|
|
287
310
|
card = {
|
|
288
311
|
"config": {"wide_screen_mode": True},
|
|
289
312
|
"header": {"title": {"tag": "plain_text", "content": title}, "template": color},
|
|
290
313
|
"elements": elements,
|
|
291
314
|
}
|
|
292
|
-
return await
|
|
293
|
-
f"{_FEISHU_API}/im/v1/messages/{message_id}/reply",
|
|
294
|
-
token,
|
|
295
|
-
{"msg_type": "interactive", "content": json.dumps(card)},
|
|
296
|
-
)
|
|
315
|
+
return await _send_message("reply", message_id, "interactive", json.dumps(card))
|
|
297
316
|
|
|
298
317
|
|
|
299
318
|
async def send_card_to_chat(chat_id: str, title: str, body: str,
|
|
@@ -305,31 +324,13 @@ async def send_card_to_chat(chat_id: str, title: str, body: str,
|
|
|
305
324
|
was never read, so every proactive send failed without a trace. Nothing
|
|
306
325
|
scheduled depended on it until the shipper digest.
|
|
307
326
|
"""
|
|
308
|
-
token = await _get_access_token()
|
|
309
|
-
if not token:
|
|
310
|
-
return False
|
|
311
327
|
elements = _build_card_elements(body)
|
|
312
328
|
card = {
|
|
313
329
|
"config": {"wide_screen_mode": True},
|
|
314
330
|
"header": {"title": {"tag": "plain_text", "content": title}, "template": color},
|
|
315
331
|
"elements": elements,
|
|
316
332
|
}
|
|
317
|
-
|
|
318
|
-
import httpx
|
|
319
|
-
async with httpx.AsyncClient(timeout=15) as client:
|
|
320
|
-
resp = await client.post(
|
|
321
|
-
f"{_FEISHU_API}/im/v1/messages?receive_id_type={receive_id_type}",
|
|
322
|
-
headers={"Authorization": f"Bearer {token}"},
|
|
323
|
-
json={
|
|
324
|
-
"receive_id": chat_id,
|
|
325
|
-
"msg_type": "interactive",
|
|
326
|
-
"content": json.dumps(card),
|
|
327
|
-
},
|
|
328
|
-
)
|
|
329
|
-
result = resp.json()
|
|
330
|
-
except Exception as exc:
|
|
331
|
-
logger.warning("send_card_to_chat failed: %s", exc)
|
|
332
|
-
return False
|
|
333
|
+
result = await _send_message("send", chat_id, "interactive", json.dumps(card), receive_id_type) or {}
|
|
333
334
|
if result.get("code") != 0:
|
|
334
335
|
logger.warning("send_card_to_chat rejected: code=%s msg=%s", result.get("code"), result.get("msg"))
|
|
335
336
|
return False
|
|
@@ -1117,6 +1118,104 @@ async def _send_digest_now(conversation: str, message_id: str) -> None:
|
|
|
1117
1118
|
await reply_card(message_id, digest.title, digest.body, "orange")
|
|
1118
1119
|
|
|
1119
1120
|
|
|
1121
|
+
# ── Approvals (apps/channels/approvals.py) ────────────────────────────────────
|
|
1122
|
+
|
|
1123
|
+
def _approval_card(approval) -> Dict[str, Any]:
|
|
1124
|
+
"""The request as a card: buttons while pending, the outcome once decided."""
|
|
1125
|
+
from aria_code.apps.channels.approvals import PENDING, status_label
|
|
1126
|
+
|
|
1127
|
+
elements = _build_card_elements(approval.summary)
|
|
1128
|
+
if approval.status == PENDING:
|
|
1129
|
+
elements.append({"tag": "note", "elements": [{"tag": "plain_text", "content":
|
|
1130
|
+
f"审批编号 {approval.id[:8]} · 24 小时内有效 · 批准后生成采购单草稿文件,不会自动下单"}]})
|
|
1131
|
+
elements.append({"tag": "action", "actions": [
|
|
1132
|
+
{"tag": "button", "type": "primary", "text": {"tag": "plain_text", "content": "批准"},
|
|
1133
|
+
"value": {"aria_approval": approval.id, "decision": "approve"}},
|
|
1134
|
+
{"tag": "button", "type": "danger", "text": {"tag": "plain_text", "content": "驳回"},
|
|
1135
|
+
"value": {"aria_approval": approval.id, "decision": "reject"}},
|
|
1136
|
+
]})
|
|
1137
|
+
template = "orange"
|
|
1138
|
+
else:
|
|
1139
|
+
outcome = f"{status_label(approval.status)} · {approval.decided_by}"
|
|
1140
|
+
# The file name, not the host path; a failure's details stay in the
|
|
1141
|
+
# approval record and the log, not in the client's group.
|
|
1142
|
+
if approval.status == "approved" and approval.result:
|
|
1143
|
+
outcome += f"\n已生成:{Path(approval.result).name}"
|
|
1144
|
+
elif approval.status == "failed":
|
|
1145
|
+
outcome += "\n详情已记录在审批记录中"
|
|
1146
|
+
elements.append({"tag": "note", "elements": [{"tag": "plain_text", "content": outcome}]})
|
|
1147
|
+
template = "green" if approval.status == "approved" else "grey"
|
|
1148
|
+
return {
|
|
1149
|
+
"config": {"wide_screen_mode": True, "update_multi": True},
|
|
1150
|
+
"header": {"title": {"tag": "plain_text", "content": f"🧾 {approval.owner_id} 采购单草稿"},
|
|
1151
|
+
"template": template},
|
|
1152
|
+
"elements": elements,
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
async def _request_reorder(inbound: InboundMessage, message_id: str) -> None:
|
|
1157
|
+
"""/补货: propose a purchase-order draft from the reorder list, for approval."""
|
|
1158
|
+
from aria_code.apps.channels.approvals import ApprovalStore, propose_reorder
|
|
1159
|
+
from aria_code.apps.channels.digest import feeds_for, load_feeds
|
|
1160
|
+
|
|
1161
|
+
owner = _conversation_store().owner_for(inbound.key)
|
|
1162
|
+
if not owner:
|
|
1163
|
+
await reply_text(message_id, "本群未绑定货主,无法发起补货审批。管理员可发送 /owner <货主ID> 绑定。")
|
|
1164
|
+
return
|
|
1165
|
+
try:
|
|
1166
|
+
inventory = feeds_for(owner, load_feeds()).get("inventory")
|
|
1167
|
+
if not inventory:
|
|
1168
|
+
raise ValueError(f"no inventory feed configured for {owner}")
|
|
1169
|
+
proposal = propose_reorder(owner, inventory)
|
|
1170
|
+
except Exception as exc:
|
|
1171
|
+
logger.warning("reorder proposal for %s failed: %s", owner, exc)
|
|
1172
|
+
await reply_text(message_id, "暂时无法生成补货建议,已记录到运维日志。")
|
|
1173
|
+
return
|
|
1174
|
+
if proposal is None:
|
|
1175
|
+
await reply_text(message_id, f"{owner}:当前没有需要补货的 SKU。")
|
|
1176
|
+
return
|
|
1177
|
+
summary, payload = proposal
|
|
1178
|
+
approval = ApprovalStore(_conversation_db_path()).request(
|
|
1179
|
+
conversation=inbound.key, owner_id=owner, kind="purchase_order_draft", payload=payload,
|
|
1180
|
+
summary=f"**建议订货**\n{summary}\n\n数量未计入起订量和箱规,请审批人核对。",
|
|
1181
|
+
requested_by=f"feishu:{inbound.sender_id}",
|
|
1182
|
+
)
|
|
1183
|
+
await _send_message("reply", message_id, "interactive", json.dumps(_approval_card(approval)))
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
async def _handle_card_action(event: Dict[str, Any], *, authorized_by_binding: bool = False) -> Dict[str, Any]:
|
|
1187
|
+
"""An approve/reject press. The response's toast and card are what the presser sees."""
|
|
1188
|
+
from aria_code.apps.channels.approvals import ApprovalStore, can_decide
|
|
1189
|
+
|
|
1190
|
+
operator = event.get("operator") or {}
|
|
1191
|
+
ids = tuple(i for i in (operator.get("open_id", ""), operator.get("user_id", "")) if i)
|
|
1192
|
+
value = (event.get("action") or {}).get("value") or {}
|
|
1193
|
+
chat_id = (event.get("context") or {}).get("open_chat_id", "")
|
|
1194
|
+
approval_id = str(value.get("aria_approval", ""))
|
|
1195
|
+
if not approval_id:
|
|
1196
|
+
return {}
|
|
1197
|
+
|
|
1198
|
+
def toast(kind: str, text: str, card=None) -> Dict[str, Any]:
|
|
1199
|
+
out: Dict[str, Any] = {"toast": {"type": kind, "content": text}}
|
|
1200
|
+
if card is not None:
|
|
1201
|
+
out["card"] = {"type": "raw", "data": card}
|
|
1202
|
+
return out
|
|
1203
|
+
|
|
1204
|
+
if not authorized_by_binding and not _is_allowed_user(*ids):
|
|
1205
|
+
return toast("error", "你还没有使用 Aria 的权限。")
|
|
1206
|
+
conversation = f"feishu:{chat_id}"
|
|
1207
|
+
decision = ApprovalStore(_conversation_db_path()).decide(
|
|
1208
|
+
approval_id,
|
|
1209
|
+
conversation=conversation,
|
|
1210
|
+
current_owner=_conversation_store().owner_for(conversation),
|
|
1211
|
+
decided_by=f"feishu:{ids[0] if ids else ''}",
|
|
1212
|
+
approve=value.get("decision") == "approve",
|
|
1213
|
+
authorised=can_decide("feishu", ids),
|
|
1214
|
+
)
|
|
1215
|
+
card = _approval_card(decision.approval) if decision.approval is not None else None
|
|
1216
|
+
return toast("success" if decision.ok else "error", decision.message, card)
|
|
1217
|
+
|
|
1218
|
+
|
|
1120
1219
|
async def send_digest_card(chat_id: str, title: str, body: str) -> bool:
|
|
1121
1220
|
"""The Feishu sender for apps.channels.digest.run_digests."""
|
|
1122
1221
|
return await send_card_to_chat(chat_id, title, body, "orange")
|
|
@@ -1144,6 +1243,10 @@ async def dispatch_event(raw: Dict[str, Any], *, authorized_by_binding: bool = F
|
|
|
1144
1243
|
event = raw.get("event", {})
|
|
1145
1244
|
event_type = header.get("event_type") or raw.get("type", "")
|
|
1146
1245
|
|
|
1246
|
+
# A press on an approval card's button (callback schema 2.0).
|
|
1247
|
+
if event_type == "card.action.trigger":
|
|
1248
|
+
return await _handle_card_action(event, authorized_by_binding=authorized_by_binding)
|
|
1249
|
+
|
|
1147
1250
|
if event_type not in ("im.message.receive_v1", "message"):
|
|
1148
1251
|
return {"code": 0}
|
|
1149
1252
|
|
|
@@ -1189,6 +1292,13 @@ async def dispatch_event(raw: Dict[str, Any], *, authorized_by_binding: bool = F
|
|
|
1189
1292
|
if msg.get("chat_type") != "p2p" and msg_type not in ("text", "post"):
|
|
1190
1293
|
return {"code": 0}
|
|
1191
1294
|
|
|
1295
|
+
# Attachments are downloaded with the app's credentials, which relay mode
|
|
1296
|
+
# does not have on this machine; say so instead of failing silently.
|
|
1297
|
+
if msg_type in ("audio", "image", "file") and not (
|
|
1298
|
+
os.environ.get("FEISHU_APP_ID") and os.environ.get("FEISHU_APP_SECRET")):
|
|
1299
|
+
await reply_text(msg_id, "中继模式下暂不支持图片、语音和文件,请直接发送文字。")
|
|
1300
|
+
return {"code": 0}
|
|
1301
|
+
|
|
1192
1302
|
# ── Text message ──────────────────────────────────────────────────────────
|
|
1193
1303
|
if msg_type == "text":
|
|
1194
1304
|
text = _strip_mentions(content.get("text", ""))
|
|
@@ -1206,6 +1316,9 @@ async def dispatch_event(raw: Dict[str, Any], *, authorized_by_binding: bool = F
|
|
|
1206
1316
|
if text.strip().lower() in ("/digest", "/简报"):
|
|
1207
1317
|
asyncio.create_task(_send_digest_now(inbound.key, msg_id))
|
|
1208
1318
|
return {"code": 0}
|
|
1319
|
+
if text.strip().lower() in ("/reorder", "/补货"):
|
|
1320
|
+
asyncio.create_task(_request_reorder(inbound, msg_id))
|
|
1321
|
+
return {"code": 0}
|
|
1209
1322
|
|
|
1210
1323
|
# A task copies the context it is created in, so every aria subprocess
|
|
1211
1324
|
# the tasks below start runs under this conversation's shipper scope.
|