aria-code 0.167.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. aria_bots/__init__.py +7 -0
  2. aria_bots/channels/README.md +97 -0
  3. aria_bots/channels/__init__.py +1 -0
  4. aria_bots/channels/approvals.py +263 -0
  5. aria_bots/channels/conversation.py +280 -0
  6. aria_bots/channels/digest.py +186 -0
  7. aria_bots/channels/registry.py +95 -0
  8. aria_bots/engine.py +144 -0
  9. aria_bots/feishu_bot.py +1385 -0
  10. aria_bots/logistics/__init__.py +1 -0
  11. aria_bots/logistics/carriers.py +253 -0
  12. aria_bots/logistics/freight.py +154 -0
  13. aria_bots/logistics/inventory.py +242 -0
  14. aria_bots/logistics/mcp_server.py +156 -0
  15. aria_bots/logistics/records.py +119 -0
  16. aria_bots/logistics/tenancy.py +152 -0
  17. aria_bots/market.py +91 -0
  18. aria_bots/relay_client.py +326 -0
  19. aria_bots/telegram_bot.py +299 -0
  20. aria_code/__init__.py +111 -0
  21. aria_code/_bin/aria-native.exe +0 -0
  22. aria_code/_bin/aria-runtime.exe +0 -0
  23. aria_code/_version.py +20 -0
  24. aria_code/account_memory.py +296 -0
  25. aria_code/account_session.py +166 -0
  26. aria_code/adk_apps/__init__.py +1 -0
  27. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  28. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  29. aria_code/adk_apps/aria_research/__init__.py +1 -0
  30. aria_code/adk_apps/aria_research/agent.py +31 -0
  31. aria_code/agents/__init__.py +49 -0
  32. aria_code/agents/base.py +329 -0
  33. aria_code/agents/code_review.py +200 -0
  34. aria_code/agents/deep/__init__.py +37 -0
  35. aria_code/agents/deep/calibration_loop.py +144 -0
  36. aria_code/agents/deep/critic.py +125 -0
  37. aria_code/agents/deep/deepen.py +193 -0
  38. aria_code/agents/deep/models.py +149 -0
  39. aria_code/agents/deep/pipeline.py +164 -0
  40. aria_code/agents/deep/quant_fusion.py +192 -0
  41. aria_code/agents/deep/themes.py +95 -0
  42. aria_code/agents/deep/tiers.py +106 -0
  43. aria_code/agents/engineering/__init__.py +14 -0
  44. aria_code/agents/engineering/coder.py +222 -0
  45. aria_code/agents/engineering/tester.py +145 -0
  46. aria_code/agents/financial/__init__.py +21 -0
  47. aria_code/agents/financial/cashflow_burn.py +119 -0
  48. aria_code/agents/financial/catalyst.py +279 -0
  49. aria_code/agents/financial/corporate_finance.py +175 -0
  50. aria_code/agents/financial/debate.py +224 -0
  51. aria_code/agents/financial/earnings.py +315 -0
  52. aria_code/agents/financial/fundamental.py +178 -0
  53. aria_code/agents/financial/macro.py +111 -0
  54. aria_code/agents/financial/news.py +231 -0
  55. aria_code/agents/financial/risk.py +146 -0
  56. aria_code/agents/financial/sector.py +279 -0
  57. aria_code/agents/financial/strategist.py +121 -0
  58. aria_code/agents/financial/stripe_revenue.py +127 -0
  59. aria_code/agents/financial/synthesis.py +274 -0
  60. aria_code/agents/financial/technical.py +277 -0
  61. aria_code/agents/orchestrator.py +44 -0
  62. aria_code/agents/portfolio_agent.py +392 -0
  63. aria_code/agents/realty/__init__.py +62 -0
  64. aria_code/agents/realty/asset_diagnosis.py +152 -0
  65. aria_code/agents/realty/business_match.py +166 -0
  66. aria_code/agents/realty/cashflow_verify.py +209 -0
  67. aria_code/agents/realty/contract_rules.py +210 -0
  68. aria_code/agents/realty/energy_anomaly.py +189 -0
  69. aria_code/agents/realty/exit_settlement.py +208 -0
  70. aria_code/agents/realty/fulfillment_risk.py +206 -0
  71. aria_code/agents/realty/ops_optimize.py +160 -0
  72. aria_code/agents/realty/revenue_share.py +215 -0
  73. aria_code/agents/registry.py +168 -0
  74. aria_code/agents/signal_scheme.py +111 -0
  75. aria_code/agents/sports/__init__.py +0 -0
  76. aria_code/agents/sports/football_agent.py +197 -0
  77. aria_code/agents/supervisor.py +113 -0
  78. aria_code/agents/team.py +500 -0
  79. aria_code/agents/video/__init__.py +16 -0
  80. aria_code/agents/video/director.py +376 -0
  81. aria_code/agents/video/qa_agent.py +143 -0
  82. aria_code/agents/video/script_doctor.py +112 -0
  83. aria_code/agents/warehouse/__init__.py +25 -0
  84. aria_code/agents/warehouse/contracts.py +26 -0
  85. aria_code/agents/warehouse/dashboard.py +155 -0
  86. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  87. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  88. aria_code/agents/warehouse/inventory_health.py +24 -0
  89. aria_code/agents/warehouse/local_run.py +71 -0
  90. aria_code/agents/warehouse/local_snapshot.py +132 -0
  91. aria_code/agents/warehouse/logistics_cost.py +84 -0
  92. aria_code/agents/warehouse/logistics_sync.py +21 -0
  93. aria_code/agents/warehouse/navigation.schema.json +110 -0
  94. aria_code/agents/warehouse/task_agent.py +172 -0
  95. aria_code/agents/warehouse/workflow.py +31 -0
  96. aria_code/aliyun_data_client.py +4 -0
  97. aria_code/apps/README.md +12 -0
  98. aria_code/apps/__init__.py +2 -0
  99. aria_code/apps/channels/README.md +9 -0
  100. aria_code/apps/channels/__init__.py +17 -0
  101. aria_code/apps/channels/approvals.py +11 -0
  102. aria_code/apps/channels/conversation.py +11 -0
  103. aria_code/apps/channels/digest.py +11 -0
  104. aria_code/apps/channels/intake.py +92 -0
  105. aria_code/apps/channels/registry.py +11 -0
  106. aria_code/apps/channels/tradingview.py +94 -0
  107. aria_code/apps/cli/README.md +13 -0
  108. aria_code/apps/cli/__init__.py +2 -0
  109. aria_code/apps/cli/_optional.py +120 -0
  110. aria_code/apps/cli/app_server.py +656 -0
  111. aria_code/apps/cli/auto_update.py +125 -0
  112. aria_code/apps/cli/bootstrap.py +206 -0
  113. aria_code/apps/cli/broker_render.py +206 -0
  114. aria_code/apps/cli/chat_turn.py +1327 -0
  115. aria_code/apps/cli/cloud_models.py +231 -0
  116. aria_code/apps/cli/codegen_paths.py +29 -0
  117. aria_code/apps/cli/commands/__init__.py +34 -0
  118. aria_code/apps/cli/commands/_business_render.py +78 -0
  119. aria_code/apps/cli/commands/_ui.py +71 -0
  120. aria_code/apps/cli/commands/analysis_cmds.py +378 -0
  121. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  122. aria_code/apps/cli/commands/auth_cmds.py +215 -0
  123. aria_code/apps/cli/commands/backtest_cmds.py +2518 -0
  124. aria_code/apps/cli/commands/broker_cmds.py +1236 -0
  125. aria_code/apps/cli/commands/business_workflow_cmds.py +379 -0
  126. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  127. aria_code/apps/cli/commands/catalog.py +189 -0
  128. aria_code/apps/cli/commands/core_cmds.py +2748 -0
  129. aria_code/apps/cli/commands/data_cmds.py +521 -0
  130. aria_code/apps/cli/commands/diagnostic_cmds.py +285 -0
  131. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  132. aria_code/apps/cli/commands/engineering_cmds.py +399 -0
  133. aria_code/apps/cli/commands/file_cmds.py +312 -0
  134. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  135. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  136. aria_code/apps/cli/commands/market.py +544 -0
  137. aria_code/apps/cli/commands/market_cmds.py +1419 -0
  138. aria_code/apps/cli/commands/market_context.py +432 -0
  139. aria_code/apps/cli/commands/market_render.py +7 -0
  140. aria_code/apps/cli/commands/model_cmds.py +2374 -0
  141. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  142. aria_code/apps/cli/commands/orchestrator_cmds.py +181 -0
  143. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  144. aria_code/apps/cli/commands/portfolio_cmds.py +1316 -0
  145. aria_code/apps/cli/commands/report.py +476 -0
  146. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  147. aria_code/apps/cli/commands/session_cmds.py +236 -0
  148. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  149. aria_code/apps/cli/commands/team.py +723 -0
  150. aria_code/apps/cli/commands/team_render.py +8 -0
  151. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  152. aria_code/apps/cli/commands/warehouse_cmds.py +297 -0
  153. aria_code/apps/cli/commands/workflow_cmds.py +629 -0
  154. aria_code/apps/cli/commands/workspace_cmds.py +1543 -0
  155. aria_code/apps/cli/config_paths.py +73 -0
  156. aria_code/apps/cli/config_store.py +158 -0
  157. aria_code/apps/cli/constants.py +88 -0
  158. aria_code/apps/cli/context.py +34 -0
  159. aria_code/apps/cli/conversation_policy.py +53 -0
  160. aria_code/apps/cli/deterministic.py +200 -0
  161. aria_code/apps/cli/direct.py +48 -0
  162. aria_code/apps/cli/earnings_view.py +172 -0
  163. aria_code/apps/cli/endpoint_migration.py +64 -0
  164. aria_code/apps/cli/exec_events.py +255 -0
  165. aria_code/apps/cli/file_references.py +155 -0
  166. aria_code/apps/cli/finance_service_catalog.py +111 -0
  167. aria_code/apps/cli/football_reports.py +231 -0
  168. aria_code/apps/cli/github_app_auth.py +135 -0
  169. aria_code/apps/cli/google_login.py +239 -0
  170. aria_code/apps/cli/handlers/__init__.py +11 -0
  171. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  172. aria_code/apps/cli/handlers/chart_handlers.py +1314 -0
  173. aria_code/apps/cli/handlers/market_handlers.py +2570 -0
  174. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  175. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  176. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  177. aria_code/apps/cli/headless.py +352 -0
  178. aria_code/apps/cli/helpers.py +326 -0
  179. aria_code/apps/cli/hooks.py +180 -0
  180. aria_code/apps/cli/i18n.py +310 -0
  181. aria_code/apps/cli/intent.py +136 -0
  182. aria_code/apps/cli/intent_router.py +305 -0
  183. aria_code/apps/cli/intent_shadow.py +72 -0
  184. aria_code/apps/cli/intent_signals.py +347 -0
  185. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  186. aria_code/apps/cli/local_tool_schemas.py +550 -0
  187. aria_code/apps/cli/main.py +39 -0
  188. aria_code/apps/cli/market_hours.py +100 -0
  189. aria_code/apps/cli/market_metadata.py +135 -0
  190. aria_code/apps/cli/market_universe.py +487 -0
  191. aria_code/apps/cli/message_processing.py +310 -0
  192. aria_code/apps/cli/mixin_binding.py +32 -0
  193. aria_code/apps/cli/model_catalog.py +652 -0
  194. aria_code/apps/cli/model_probe.py +169 -0
  195. aria_code/apps/cli/model_retirement.py +65 -0
  196. aria_code/apps/cli/native_branding.py +12 -0
  197. aria_code/apps/cli/native_bridge.py +118 -0
  198. aria_code/apps/cli/native_entry.py +58 -0
  199. aria_code/apps/cli/pdf_report.py +977 -0
  200. aria_code/apps/cli/plan_mode.py +139 -0
  201. aria_code/apps/cli/plotly_html.py +15 -0
  202. aria_code/apps/cli/prediction_feedback.py +202 -0
  203. aria_code/apps/cli/preflight.py +502 -0
  204. aria_code/apps/cli/project_aria.py +60 -0
  205. aria_code/apps/cli/prompt_assembly.py +78 -0
  206. aria_code/apps/cli/prompts/__init__.py +0 -0
  207. aria_code/apps/cli/prompts/coding.py +71 -0
  208. aria_code/apps/cli/prompts/select.py +193 -0
  209. aria_code/apps/cli/prompts/system_prompts.py +562 -0
  210. aria_code/apps/cli/prompts/ui.py +436 -0
  211. aria_code/apps/cli/provider_endpoints.py +237 -0
  212. aria_code/apps/cli/provider_keys.py +73 -0
  213. aria_code/apps/cli/providers/__init__.py +1 -0
  214. aria_code/apps/cli/providers/base.py +775 -0
  215. aria_code/apps/cli/providers/chat_routing.py +139 -0
  216. aria_code/apps/cli/providers/collaboration.py +98 -0
  217. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  218. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  219. aria_code/apps/cli/providers/llm/ollama_stream.py +1574 -0
  220. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  221. aria_code/apps/cli/providers/llm/sse_stream.py +298 -0
  222. aria_code/apps/cli/providers/runtime_bridge.py +586 -0
  223. aria_code/apps/cli/providers/vertexai_stream.py +592 -0
  224. aria_code/apps/cli/release_download.py +159 -0
  225. aria_code/apps/cli/review_runner.py +111 -0
  226. aria_code/apps/cli/runtime_consumer.py +769 -0
  227. aria_code/apps/cli/sandbox.py +32 -0
  228. aria_code/apps/cli/session_export.py +120 -0
  229. aria_code/apps/cli/session_jsonl.py +208 -0
  230. aria_code/apps/cli/session_refresh.py +123 -0
  231. aria_code/apps/cli/session_store.py +125 -0
  232. aria_code/apps/cli/skills_catalog.py +273 -0
  233. aria_code/apps/cli/task_isolation.py +211 -0
  234. aria_code/apps/cli/terminal_chrome.py +412 -0
  235. aria_code/apps/cli/todo_tracker.py +190 -0
  236. aria_code/apps/cli/tool_executor.py +932 -0
  237. aria_code/apps/cli/tool_registry.py +34 -0
  238. aria_code/apps/cli/tool_scope.py +113 -0
  239. aria_code/apps/cli/tools/__init__.py +40 -0
  240. aria_code/apps/cli/tools/context.py +46 -0
  241. aria_code/apps/cli/tools/file_tools.py +181 -0
  242. aria_code/apps/cli/tools/market_tools.py +626 -0
  243. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  244. aria_code/apps/cli/tools/system_tools.py +656 -0
  245. aria_code/apps/cli/tools/write_tools.py +961 -0
  246. aria_code/apps/cli/tradingview_bridge.py +529 -0
  247. aria_code/apps/cli/transactions.py +269 -0
  248. aria_code/apps/cli/turn_planning.py +137 -0
  249. aria_code/apps/cli/update_check.py +257 -0
  250. aria_code/apps/cli/updater.py +373 -0
  251. aria_code/apps/cli/utils/__init__.py +0 -0
  252. aria_code/apps/cli/utils/market_detect.py +1663 -0
  253. aria_code/apps/cli/web_login.py +136 -0
  254. aria_code/apps/cli/workflow_runner.py +127 -0
  255. aria_code/apps/cli/workspace_route.py +121 -0
  256. aria_code/apps/daemon/README.md +14 -0
  257. aria_code/apps/vscode/README.md +115 -0
  258. aria_code/apps/vscode/package.json +70 -0
  259. aria_code/aria_cli.py +5244 -0
  260. aria_code/aria_daemon.py +1372 -0
  261. aria_code/aria_feishu_bot.py +16 -0
  262. aria_code/aria_mcp_server.py +61 -0
  263. aria_code/aria_relay_client.py +4 -0
  264. aria_code/aria_telegram_bot.py +11 -0
  265. aria_code/ariarc.py +385 -0
  266. aria_code/artifacts.py +581 -0
  267. aria_code/backtest_engine.py +4 -0
  268. aria_code/backtest_report.py +4 -0
  269. aria_code/brokers/__init__.py +78 -0
  270. aria_code/brokers/automation.py +193 -0
  271. aria_code/brokers/base.py +231 -0
  272. aria_code/brokers/capabilities.py +264 -0
  273. aria_code/brokers/cn/__init__.py +10 -0
  274. aria_code/brokers/cn/easytrader_broker.py +193 -0
  275. aria_code/brokers/cn/futu_broker.py +194 -0
  276. aria_code/brokers/cn/longbridge_broker.py +190 -0
  277. aria_code/brokers/cn/tiger_broker.py +196 -0
  278. aria_code/brokers/cn/xtquant_broker.py +225 -0
  279. aria_code/brokers/config.py +414 -0
  280. aria_code/brokers/intl/__init__.py +5 -0
  281. aria_code/brokers/intl/alpaca_broker.py +183 -0
  282. aria_code/brokers/intl/ibkr_broker.py +215 -0
  283. aria_code/brokers/intl/trading212_broker.py +183 -0
  284. aria_code/brokers/intl/webull_broker.py +156 -0
  285. aria_code/brokers/paper_broker.py +266 -0
  286. aria_code/brokers/planning.py +296 -0
  287. aria_code/brokers/registry.py +213 -0
  288. aria_code/brokers/trading.py +267 -0
  289. aria_code/canva_client.py +4 -0
  290. aria_code/change_store.py +127 -0
  291. aria_code/clients/__init__.py +0 -0
  292. aria_code/clients/aliyun_data_client.py +660 -0
  293. aria_code/clients/aria_relay_client.py +16 -0
  294. aria_code/clients/canva_client.py +284 -0
  295. aria_code/clients/figma_client.py +100 -0
  296. aria_code/clients/football_data_client.py +1671 -0
  297. aria_code/clients/kling_video_client.py +182 -0
  298. aria_code/clients/market_data_client.py +1985 -0
  299. aria_code/clients/openai_image_client.py +242 -0
  300. aria_code/clients/runway_video_client.py +157 -0
  301. aria_code/clients/warehouse_erp_client.py +105 -0
  302. aria_code/cloud_memory.py +190 -0
  303. aria_code/command_safety.py +19 -0
  304. aria_code/computer_use_server.py +276 -0
  305. aria_code/computer_use_tools.py +4 -0
  306. aria_code/dashboard_generator.py +579 -0
  307. aria_code/data_analysis_tools.py +4 -0
  308. aria_code/data_cleaner.py +483 -0
  309. aria_code/data_service.py +513 -0
  310. aria_code/datasources/__init__.py +23 -0
  311. aria_code/datasources/base.py +166 -0
  312. aria_code/datasources/router.py +253 -0
  313. aria_code/datasources/sec_statements.py +217 -0
  314. aria_code/datasources/sources/__init__.py +15 -0
  315. aria_code/datasources/sources/akshare_source.py +269 -0
  316. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  317. aria_code/datasources/sources/edgar_source.py +219 -0
  318. aria_code/datasources/sources/finnhub_source.py +198 -0
  319. aria_code/datasources/sources/fred_source.py +223 -0
  320. aria_code/datasources/sources/tushare_source.py +143 -0
  321. aria_code/datasources/sources/web_scraper_source.py +278 -0
  322. aria_code/datasources/sources/world_bank_source.py +206 -0
  323. aria_code/datasources/sources/yfinance_source.py +152 -0
  324. aria_code/doctor.py +860 -0
  325. aria_code/domain/__init__.py +0 -0
  326. aria_code/domain/_finance_core/__init__.py +5 -0
  327. aria_code/domain/_finance_core/backtest_engine.py +325 -0
  328. aria_code/domain/_finance_core/performance_stats.py +101 -0
  329. aria_code/domain/backtest_engine.py +75 -0
  330. aria_code/domain/backtest_report.py +488 -0
  331. aria_code/domain/finance_formulas.py +389 -0
  332. aria_code/domain/performance_stats.py +6 -0
  333. aria_code/domain/portfolio_ledger.py +307 -0
  334. aria_code/domain/strategy_vault.py +421 -0
  335. aria_code/evals/__init__.py +37 -0
  336. aria_code/evals/behavior.py +113 -0
  337. aria_code/evals/gap.py +93 -0
  338. aria_code/evals/harness.py +949 -0
  339. aria_code/evals/review_probe.py +132 -0
  340. aria_code/evals/runner.py +425 -0
  341. aria_code/evals/scorecard.py +322 -0
  342. aria_code/evals/summary.py +125 -0
  343. aria_code/external_agent_runner.py +115 -0
  344. aria_code/figma_client.py +4 -0
  345. aria_code/file_analysis_tools.py +4 -0
  346. aria_code/finance_formulas.py +4 -0
  347. aria_code/football_data_client.py +4 -0
  348. aria_code/image_gen_tools.py +4 -0
  349. aria_code/intent_classifier.py +459 -0
  350. aria_code/kling_video_client.py +4 -0
  351. aria_code/licensing.py +151 -0
  352. aria_code/local_finance_tools.py +4 -0
  353. aria_code/local_image_provider.py +4 -0
  354. aria_code/local_llm_provider.py +4 -0
  355. aria_code/macro_tools.py +4 -0
  356. aria_code/markdown_pdf.py +289 -0
  357. aria_code/market_data_client.py +4 -0
  358. aria_code/mcp_client.py +744 -0
  359. aria_code/memory_manager.py +273 -0
  360. aria_code/model_capability.py +512 -0
  361. aria_code/notification_tools.py +4 -0
  362. aria_code/openai_image_client.py +4 -0
  363. aria_code/packages/__init__.py +26 -0
  364. aria_code/packages/adk_bridge/__init__.py +11 -0
  365. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  366. aria_code/packages/adk_bridge/market_tools.py +125 -0
  367. aria_code/packages/aria_agents/__init__.py +5 -0
  368. aria_code/packages/aria_agents/manifest.py +78 -0
  369. aria_code/packages/aria_core/__init__.py +34 -0
  370. aria_code/packages/aria_core/architecture.py +269 -0
  371. aria_code/packages/aria_core/export.py +147 -0
  372. aria_code/packages/aria_core/manifest.py +65 -0
  373. aria_code/packages/aria_core/paths.py +57 -0
  374. aria_code/packages/aria_core/secure_file.py +68 -0
  375. aria_code/packages/aria_infra/__init__.py +15 -0
  376. aria_code/packages/aria_infra/arthera.py +58 -0
  377. aria_code/packages/aria_infra/doctor.py +246 -0
  378. aria_code/packages/aria_infra/product.py +40 -0
  379. aria_code/packages/aria_mcp/__init__.py +25 -0
  380. aria_code/packages/aria_mcp/bridge.py +232 -0
  381. aria_code/packages/aria_mcp/circuit.py +82 -0
  382. aria_code/packages/aria_mcp/config.py +162 -0
  383. aria_code/packages/aria_mcp/installer.py +95 -0
  384. aria_code/packages/aria_mcp/server.py +1705 -0
  385. aria_code/packages/aria_mcp/tools.py +81 -0
  386. aria_code/packages/aria_sdk/__init__.py +19 -0
  387. aria_code/packages/aria_sdk/client.py +393 -0
  388. aria_code/packages/aria_sdk/providers.py +70 -0
  389. aria_code/packages/aria_sdk/streaming.py +75 -0
  390. aria_code/packages/aria_sdk/types.py +86 -0
  391. aria_code/packages/aria_services/__init__.py +92 -0
  392. aria_code/packages/aria_services/cache.py +60 -0
  393. aria_code/packages/aria_services/context.py +356 -0
  394. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  395. aria_code/packages/aria_services/data.py +11 -0
  396. aria_code/packages/aria_services/provider_health.py +304 -0
  397. aria_code/packages/aria_services/references.py +247 -0
  398. aria_code/packages/aria_services/registry.py +249 -0
  399. aria_code/packages/aria_services/research_protocol.py +137 -0
  400. aria_code/packages/aria_services/research_quality.py +186 -0
  401. aria_code/packages/aria_services/settings.py +160 -0
  402. aria_code/packages/aria_services/usage.py +151 -0
  403. aria_code/packages/aria_skills/__init__.py +46 -0
  404. aria_code/packages/aria_skills/catalog.py +149 -0
  405. aria_code/packages/aria_skills/loader.py +455 -0
  406. aria_code/packages/aria_skills/registry.py +84 -0
  407. aria_code/packages/aria_tools/__init__.py +5 -0
  408. aria_code/packages/aria_tools/financial/__init__.py +5 -0
  409. aria_code/packages/aria_tools/financial/_paths.py +92 -0
  410. aria_code/packages/aria_tools/registry.py +129 -0
  411. aria_code/packages/quant_engine/__init__.py +33 -0
  412. aria_code/packages/quant_engine/_namespace.py +24 -0
  413. aria_code/packages/quant_engine/backtest/__init__.py +10 -0
  414. aria_code/packages/quant_engine/backtest/core.py +53 -0
  415. aria_code/packages/quant_engine/backtest/engine.py +102 -0
  416. aria_code/packages/quant_engine/portfolio/__init__.py +9 -0
  417. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  418. aria_code/packages/quant_engine/sports/__init__.py +76 -0
  419. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  420. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  421. aria_code/packages/quant_engine/sports/elo.py +300 -0
  422. aria_code/packages/quant_engine/sports/form.py +188 -0
  423. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  424. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  425. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  426. aria_code/packages/quant_engine/stochastic/__init__.py +31 -0
  427. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  428. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  429. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  430. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  431. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  432. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  433. aria_code/packs/__init__.py +85 -0
  434. aria_code/packs/base.py +168 -0
  435. aria_code/packs/finance/__init__.py +250 -0
  436. aria_code/packs/healthcare/__init__.py +40 -0
  437. aria_code/packs/logistics/__init__.py +171 -0
  438. aria_code/packs/payments/__init__.py +139 -0
  439. aria_code/packs/realty/__init__.py +190 -0
  440. aria_code/packs/registry.py +202 -0
  441. aria_code/packs/rules.py +90 -0
  442. aria_code/plan_utils.py +194 -0
  443. aria_code/plugin_loader.py +328 -0
  444. aria_code/portfolio_ledger.py +4 -0
  445. aria_code/preview_server.py +449 -0
  446. aria_code/privacy/__init__.py +5 -0
  447. aria_code/privacy/feedback.py +123 -0
  448. aria_code/project_review.py +278 -0
  449. aria_code/project_review_api.py +235 -0
  450. aria_code/project_review_server.py +18 -0
  451. aria_code/project_tools.py +4 -0
  452. aria_code/providers/__init__.py +30 -0
  453. aria_code/providers/google_video_provider.py +256 -0
  454. aria_code/providers/llm/__init__.py +19 -0
  455. aria_code/providers/llm/anthropic.py +184 -0
  456. aria_code/providers/llm/arthera_gateway.py +90 -0
  457. aria_code/providers/llm/autoconfig.py +213 -0
  458. aria_code/providers/llm/base.py +139 -0
  459. aria_code/providers/llm/custom.py +158 -0
  460. aria_code/providers/llm/ollama.py +137 -0
  461. aria_code/providers/llm/openai_compat.py +350 -0
  462. aria_code/providers/llm/registry.py +457 -0
  463. aria_code/providers/local_image_provider.py +202 -0
  464. aria_code/providers/local_llm_provider.py +549 -0
  465. aria_code/providers/ollama_models.py +79 -0
  466. aria_code/providers/openai_params.py +32 -0
  467. aria_code/providers/tool_messages.py +100 -0
  468. aria_code/realty_data_tools.py +4 -0
  469. aria_code/report_exporters.py +150 -0
  470. aria_code/report_generator.py +1764 -0
  471. aria_code/review_service.py +497 -0
  472. aria_code/runtime/__init__.py +176 -0
  473. aria_code/runtime/acceptance.py +632 -0
  474. aria_code/runtime/agent_loop.py +1851 -0
  475. aria_code/runtime/agent_profiles.py +75 -0
  476. aria_code/runtime/approval.py +71 -0
  477. aria_code/runtime/baseline.py +219 -0
  478. aria_code/runtime/budget.py +232 -0
  479. aria_code/runtime/checkpoints.py +481 -0
  480. aria_code/runtime/consult.py +65 -0
  481. aria_code/runtime/contract.py +282 -0
  482. aria_code/runtime/delivery.py +432 -0
  483. aria_code/runtime/events.py +113 -0
  484. aria_code/runtime/gateway.py +167 -0
  485. aria_code/runtime/lsp.py +484 -0
  486. aria_code/runtime/native_index.py +153 -0
  487. aria_code/runtime/orchestrator.py +55 -0
  488. aria_code/runtime/processes.py +343 -0
  489. aria_code/runtime/project_graph.py +614 -0
  490. aria_code/runtime/repo_map.py +712 -0
  491. aria_code/runtime/research_bundle.py +105 -0
  492. aria_code/runtime/review.py +269 -0
  493. aria_code/runtime/run_state.py +127 -0
  494. aria_code/runtime/run_store.py +522 -0
  495. aria_code/runtime/scoped_runs.py +113 -0
  496. aria_code/runtime/self_healing.py +422 -0
  497. aria_code/runtime/semantic_diff.py +171 -0
  498. aria_code/runtime/subagent.py +721 -0
  499. aria_code/runtime/symbol_edit.py +117 -0
  500. aria_code/runtime/task_brief.py +46 -0
  501. aria_code/runtime/task_context.py +145 -0
  502. aria_code/runtime/task_ledger.py +108 -0
  503. aria_code/runtime/task_orchestrator.py +90 -0
  504. aria_code/runtime/task_outcome.py +33 -0
  505. aria_code/runtime/task_verification.py +266 -0
  506. aria_code/runtime/task_worktree.py +448 -0
  507. aria_code/runtime/tool_executor.py +329 -0
  508. aria_code/runtime/tool_policy.py +107 -0
  509. aria_code/runtime/transactions.py +216 -0
  510. aria_code/runtime/windows_job.py +115 -0
  511. aria_code/runtime/workflows.py +222 -0
  512. aria_code/runtime/worktrees.py +215 -0
  513. aria_code/runway_video_client.py +4 -0
  514. aria_code/safety/__init__.py +27 -0
  515. aria_code/safety/client_isolation.py +178 -0
  516. aria_code/safety/permissions.py +339 -0
  517. aria_code/safety/risk.py +699 -0
  518. aria_code/safety/sandbox.py +148 -0
  519. aria_code/safety/service.py +102 -0
  520. aria_code/service_endpoints.py +14 -0
  521. aria_code/setup_wizard.py +684 -0
  522. aria_code/spreadsheet_tools.py +4 -0
  523. aria_code/strategy_vault.py +4 -0
  524. aria_code/tools/__init__.py +0 -0
  525. aria_code/tools/artifact_tools.py +252 -0
  526. aria_code/tools/broker_tools.py +92 -0
  527. aria_code/tools/build_quant_engine.py +97 -0
  528. aria_code/tools/code_audit_tools.py +192 -0
  529. aria_code/tools/computer_use_tools.py +509 -0
  530. aria_code/tools/data_analysis_tools.py +831 -0
  531. aria_code/tools/enterprise_finance_tools.py +202 -0
  532. aria_code/tools/extended_tools.py +240 -0
  533. aria_code/tools/file_analysis_tools.py +880 -0
  534. aria_code/tools/image_gen_tools.py +114 -0
  535. aria_code/tools/local_finance_tools.py +3488 -0
  536. aria_code/tools/logistics_carriers.py +11 -0
  537. aria_code/tools/logistics_inventory.py +11 -0
  538. aria_code/tools/logistics_io.py +11 -0
  539. aria_code/tools/logistics_tenancy.py +11 -0
  540. aria_code/tools/logistics_tools.py +11 -0
  541. aria_code/tools/macro_tools.py +412 -0
  542. aria_code/tools/notification_tools.py +249 -0
  543. aria_code/tools/project_tools.py +525 -0
  544. aria_code/tools/realty_data_tools.py +662 -0
  545. aria_code/tools/spreadsheet_tools.py +399 -0
  546. aria_code/tools/stripe_tools.py +115 -0
  547. aria_code/tools/video_tools.py +500 -0
  548. aria_code/training/__init__.py +1 -0
  549. aria_code/training/compare.py +117 -0
  550. aria_code/training/prelude_commands.py +111 -0
  551. aria_code/training/prelude_eval.py +390 -0
  552. aria_code/training/prelude_real.py +183 -0
  553. aria_code/training/prelude_train.py +248 -0
  554. aria_code/training/sft_dataset.py +230 -0
  555. aria_code/training/trajectory_dataset.py +263 -0
  556. aria_code/ui/__init__.py +105 -0
  557. aria_code/ui/banner.py +404 -0
  558. aria_code/ui/completer.py +571 -0
  559. aria_code/ui/console.py +285 -0
  560. aria_code/ui/input_box.py +505 -0
  561. aria_code/ui/mentions.py +206 -0
  562. aria_code/ui/picker.py +248 -0
  563. aria_code/ui/render/__init__.py +11 -0
  564. aria_code/ui/render/actions.py +297 -0
  565. aria_code/ui/render/finance.py +1732 -0
  566. aria_code/ui/render/market.py +253 -0
  567. aria_code/ui/render/output.py +954 -0
  568. aria_code/ui/render/responsive.py +75 -0
  569. aria_code/ui/render/team.py +367 -0
  570. aria_code/ui/robot.py +239 -0
  571. aria_code/ui/startup_dashboard.py +110 -0
  572. aria_code/video_analysis.py +147 -0
  573. aria_code/video_editor.py +518 -0
  574. aria_code/video_workflow/__init__.py +8 -0
  575. aria_code/video_workflow/__main__.py +61 -0
  576. aria_code/video_workflow/engines/__init__.py +18 -0
  577. aria_code/video_workflow/engines/base.py +69 -0
  578. aria_code/video_workflow/engines/custom_model.py +204 -0
  579. aria_code/video_workflow/engines/google_veo.py +94 -0
  580. aria_code/video_workflow/engines/local_engine.py +71 -0
  581. aria_code/video_workflow/engines/registry.py +98 -0
  582. aria_code/video_workflow/google_models.py +278 -0
  583. aria_code/video_workflow/music/__init__.py +5 -0
  584. aria_code/video_workflow/music/foley_service.py +132 -0
  585. aria_code/video_workflow/music/service.py +212 -0
  586. aria_code/video_workflow/pipeline.py +620 -0
  587. aria_code/video_workflow/plan.py +202 -0
  588. aria_code/video_workflow/session.py +297 -0
  589. aria_code/workspace/__init__.py +6 -0
  590. aria_code/workspace/files.py +219 -0
  591. aria_code/workspace/verify.py +167 -0
  592. aria_code/workspace_changes.py +199 -0
  593. aria_code/workspace_service.py +196 -0
  594. aria_code/workspace_tools.py +150 -0
  595. aria_code-0.167.0.dist-info/METADATA +330 -0
  596. aria_code-0.167.0.dist-info/RECORD +601 -0
  597. aria_code-0.167.0.dist-info/WHEEL +5 -0
  598. aria_code-0.167.0.dist-info/entry_points.txt +5 -0
  599. aria_code-0.167.0.dist-info/licenses/LICENSE +201 -0
  600. aria_code-0.167.0.dist-info/licenses/NOTICE +49 -0
  601. aria_code-0.167.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,525 @@
1
+ """
2
+ project_tools.py — 项目文件夹分析引擎
3
+ ========================================
4
+ 提供 Claude Code / Codex 同等能力:
5
+ - 递归扫描项目目录,构建文件树
6
+ - 自动检测项目类型(Python / Node / Go / Rust / Java / …)
7
+ - 智能读取关键文件注入 LLM 上下文
8
+ - 跨文件 grep / 符号索引
9
+ - Git 状态集成
10
+ - 按 token 预算动态裁剪上下文
11
+
12
+ ProjectSession 生命周期:
13
+ 1. scan(path) — 扫描目录,建立索引
14
+ 2. build_llm_context — 生成注入 system prompt 的上下文块
15
+ 3. get_file / grep — LLM 工具调用时按需读取
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import fnmatch
21
+ import json
22
+ import os
23
+ import re
24
+ import subprocess
25
+ from dataclasses import dataclass, field
26
+ from pathlib import Path
27
+ from typing import Any, Dict, List, Optional, Set, Tuple
28
+
29
+ # ── 忽略规则 ──────────────────────────────────────────────────────────────────
30
+
31
+ _IGNORE_DIRS: Set[str] = {
32
+ ".git", ".hg", ".svn",
33
+ "node_modules", ".pnp",
34
+ "__pycache__", ".mypy_cache", ".ruff_cache", ".pytest_cache",
35
+ ".venv", "venv", "env", ".env",
36
+ "dist", "build", "out", "target", ".next", ".nuxt",
37
+ "coverage", ".coverage", "htmlcov",
38
+ ".idea", ".vscode", ".DS_Store",
39
+ "eggs", "*.egg-info",
40
+ }
41
+
42
+ _IGNORE_FILE_PATTERNS: List[str] = [
43
+ "*.pyc", "*.pyo", "*.pyd",
44
+ "*.so", "*.dll", "*.dylib",
45
+ "*.class", "*.jar",
46
+ "*.min.js", "*.min.css",
47
+ "*.map",
48
+ "*.lock", # package-lock.json 例外:内容有用,但体积太大
49
+ "*.log",
50
+ ".DS_Store", "Thumbs.db",
51
+ "*.bin", "*.exe", "*.whl", "*.tar.gz", "*.zip",
52
+ "*.jpg", "*.jpeg", "*.png", "*.gif", "*.webp", "*.ico",
53
+ "*.mp4", "*.mp3", "*.pdf",
54
+ ]
55
+
56
+ _BINARY_EXTENSIONS: Set[str] = {
57
+ ".pyc",".pyo",".pyd",".so",".dll",".dylib",".class",".jar",
58
+ ".bin",".exe",".whl",".tar",".gz",".zip",".rar",
59
+ ".jpg",".jpeg",".png",".gif",".bmp",".webp",".ico",
60
+ ".mp4",".mp3",".wav",".avi",".mkv",
61
+ ".pdf",".doc",".xls",".ppt",
62
+ }
63
+
64
+ # ── 项目类型指纹 ──────────────────────────────────────────────────────────────
65
+
66
+ _PROJECT_SIGNATURES: List[Tuple[str, List[str], str]] = [
67
+ # (类型名, 指纹文件列表, 主入口候选)
68
+ ("Python", ["pyproject.toml", "setup.py", "requirements.txt"], "main.py"),
69
+ ("Node.js", ["package.json"], "index.js"),
70
+ ("TypeScript", ["tsconfig.json"], "src/index.ts"),
71
+ ("Go", ["go.mod"], "main.go"),
72
+ ("Rust", ["Cargo.toml"], "src/main.rs"),
73
+ ("Java", ["pom.xml", "build.gradle"], "src/main/java"),
74
+ ("Kotlin", ["build.gradle.kts"], "src/main/kotlin"),
75
+ ("Ruby", ["Gemfile"], "main.rb"),
76
+ ("PHP", ["composer.json"], "index.php"),
77
+ ("C#", ["*.csproj", "*.sln"], "Program.cs"),
78
+ ("C/C++", ["CMakeLists.txt", "Makefile"], "main.c"),
79
+ ("Swift", ["Package.swift"], "Sources/main.swift"),
80
+ ("Dart/Flutter",["pubspec.yaml"], "lib/main.dart"),
81
+ ("Elixir", ["mix.exs"], "lib/main.ex"),
82
+ ]
83
+
84
+ # 关键配置文件(权重高,一定要读)
85
+ _KEY_CONFIG_FILES: List[str] = [
86
+ "README.md", "README.rst", "README.txt",
87
+ "pyproject.toml", "setup.py", "requirements.txt",
88
+ "package.json",
89
+ "go.mod",
90
+ "Cargo.toml",
91
+ "pom.xml",
92
+ "Makefile",
93
+ ".env.example", ".env.sample",
94
+ "docker-compose.yml", "Dockerfile",
95
+ ".github/workflows", # CI
96
+ ]
97
+
98
+ # ── 数据结构 ──────────────────────────────────────────────────────────────────
99
+
100
+ @dataclass
101
+ class FileNode:
102
+ rel_path: str
103
+ abs_path: str
104
+ size: int
105
+ ext: str
106
+ is_dir: bool = False
107
+ language: str = ""
108
+
109
+
110
+ @dataclass
111
+ class ProjectSession:
112
+ """Loaded project state — persisted in ArtheraTerminal._project_session."""
113
+ root: str = ""
114
+ name: str = ""
115
+ project_type: str = ""
116
+ languages: List[str] = field(default_factory=list)
117
+ files: List[FileNode] = field(default_factory=list)
118
+ key_contents: Dict[str, str] = field(default_factory=dict) # rel_path → text
119
+ git_info: Dict[str, Any] = field(default_factory=dict)
120
+ stats: Dict[str, Any] = field(default_factory=dict)
121
+ _tree_cache: str = field(default="", repr=False)
122
+
123
+ # ── Scan ──────────────────────────────────────────────────────────────────
124
+
125
+ def scan(self, path: str, max_files: int = 2000) -> "ProjectSession":
126
+ root = Path(path).expanduser().resolve()
127
+ if not root.exists():
128
+ raise FileNotFoundError(f"路径不存在: {root}")
129
+ if not root.is_dir():
130
+ raise ValueError(f"不是目录: {root}")
131
+
132
+ self.root = str(root)
133
+ self.name = root.name
134
+ self.files = []
135
+ self._tree_cache = ""
136
+
137
+ # Walk directory
138
+ for dirpath, dirnames, filenames in os.walk(root):
139
+ # Prune ignored dirs in-place
140
+ dirnames[:] = [
141
+ d for d in dirnames
142
+ if d not in _IGNORE_DIRS
143
+ and not d.startswith(".")
144
+ or d in {".github", ".gitlab"}
145
+ ]
146
+ # Also skip dirs matching patterns
147
+ dirnames[:] = [
148
+ d for d in dirnames
149
+ if not any(fnmatch.fnmatch(d, p) for p in ["*.egg-info", "*.dist-info"])
150
+ ]
151
+
152
+ for fname in filenames:
153
+ if len(self.files) >= max_files:
154
+ break
155
+ if any(fnmatch.fnmatch(fname, p) for p in _IGNORE_FILE_PATTERNS):
156
+ continue
157
+ fpath = Path(dirpath) / fname
158
+ try:
159
+ size = fpath.stat().st_size
160
+ except OSError:
161
+ continue
162
+ ext = fpath.suffix.lower()
163
+ if ext in _BINARY_EXTENSIONS:
164
+ continue
165
+ rel = str(fpath.relative_to(root))
166
+ self.files.append(FileNode(
167
+ rel_path=rel,
168
+ abs_path=str(fpath),
169
+ size=size,
170
+ ext=ext,
171
+ language=_ext_to_lang(ext),
172
+ ))
173
+
174
+ # Detect project type
175
+ root_names = {f.rel_path for f in self.files}
176
+ self.project_type = "Unknown"
177
+ detected_langs: List[str] = []
178
+ for ptype, fingerprints, _ in _PROJECT_SIGNATURES:
179
+ for fp in fingerprints:
180
+ if "*" in fp:
181
+ if any(fnmatch.fnmatch(r, fp) for r in root_names):
182
+ self.project_type = ptype
183
+ detected_langs.append(ptype)
184
+ break
185
+ elif fp in root_names:
186
+ self.project_type = ptype
187
+ detected_langs.append(ptype)
188
+ break
189
+ # Language frequency from extensions
190
+ lang_counts: Dict[str, int] = {}
191
+ for f in self.files:
192
+ if f.language:
193
+ lang_counts[f.language] = lang_counts.get(f.language, 0) + 1
194
+ top_langs = sorted(lang_counts, key=lang_counts.get, reverse=True)[:4]
195
+ self.languages = list(dict.fromkeys(detected_langs + top_langs))[:5]
196
+
197
+ # Stats
198
+ total_lines = 0
199
+ for f in self.files:
200
+ if f.size < 500_000 and f.ext not in _BINARY_EXTENSIONS:
201
+ try:
202
+ total_lines += Path(f.abs_path).read_text(errors="replace").count("\n")
203
+ except Exception:
204
+ pass
205
+ self.stats = {
206
+ "total_files": len(self.files),
207
+ "total_lines": total_lines,
208
+ "total_size_kb": sum(f.size for f in self.files) // 1024,
209
+ "languages": lang_counts,
210
+ }
211
+
212
+ # Read key files
213
+ self.key_contents = {}
214
+ self._load_key_files(root)
215
+
216
+ # Git info
217
+ self.git_info = _get_git_info(str(root))
218
+
219
+ return self
220
+
221
+ def _load_key_files(self, root: Path, max_chars_each: int = 4000):
222
+ """Read README + config files into key_contents."""
223
+ for rel in _KEY_CONFIG_FILES:
224
+ candidate = root / rel
225
+ if candidate.is_file():
226
+ try:
227
+ text = candidate.read_text(errors="replace")[:max_chars_each]
228
+ self.key_contents[rel] = text
229
+ except Exception:
230
+ pass
231
+
232
+ # Auto-detect main entry point
233
+ for _, fingerprints, entry in _PROJECT_SIGNATURES:
234
+ for fp in fingerprints:
235
+ if "*" in fp:
236
+ continue
237
+ if (root / fp).exists():
238
+ ep = root / entry
239
+ if ep.is_file() and entry not in self.key_contents:
240
+ try:
241
+ self.key_contents[entry] = ep.read_text(errors="replace")[:4000]
242
+ except Exception:
243
+ pass
244
+ break
245
+
246
+ # ── Tree rendering ─────────────────────────────────────────────────────────
247
+
248
+ def get_tree(self, max_lines: int = 80) -> str:
249
+ """Return ASCII file tree string."""
250
+ if self._tree_cache:
251
+ return self._tree_cache
252
+
253
+ root = Path(self.root)
254
+ # Build nested dict
255
+ tree: Dict[str, Any] = {}
256
+ for f in self.files:
257
+ parts = Path(f.rel_path).parts
258
+ node = tree
259
+ for part in parts[:-1]:
260
+ node = node.setdefault(part, {})
261
+ node[parts[-1]] = f.size
262
+
263
+ lines: List[str] = [f"{self.name}/"]
264
+ _render_tree(tree, lines, "", max_lines)
265
+ if len(lines) > max_lines:
266
+ lines = lines[:max_lines]
267
+ lines.append(f" … (仅显示前 {max_lines} 条,共 {len(self.files)} 个文件)")
268
+ result = "\n".join(lines)
269
+ self._tree_cache = result
270
+ return result
271
+
272
+ # ── LLM context ───────────────────────────────────────────────────────────
273
+
274
+ def build_llm_context(self, max_chars: int = 16_000) -> str:
275
+ """Build the system-prompt context block injected for every message."""
276
+ parts: List[str] = []
277
+ budget = max_chars
278
+
279
+ # Header
280
+ git_branch = self.git_info.get("branch", "")
281
+ header = (
282
+ f"=== 已加载项目: {self.name} ===\n"
283
+ f"路径: {self.root}\n"
284
+ f"类型: {self.project_type} | 语言: {', '.join(self.languages[:3])}\n"
285
+ f"文件: {self.stats.get('total_files',0)} 个 "
286
+ f"代码行: {self.stats.get('total_lines',0):,} "
287
+ f"大小: {self.stats.get('total_size_kb',0)} KB"
288
+ )
289
+ if git_branch:
290
+ header += f"\nGit 分支: {git_branch}"
291
+ if self.git_info.get("recent_commits"):
292
+ commits = self.git_info["recent_commits"][:3]
293
+ header += "\n最近提交:\n" + "\n".join(f" {c}" for c in commits)
294
+ parts.append(header)
295
+ budget -= len(header)
296
+
297
+ # File tree (cap at 3000 chars)
298
+ tree_str = self.get_tree(max_lines=60)
299
+ tree_block = f"\n--- 文件结构 ---\n{tree_str}"
300
+ if len(tree_block) <= min(budget, 3000):
301
+ parts.append(tree_block)
302
+ budget -= len(tree_block)
303
+
304
+ # Key file contents
305
+ if budget > 1000:
306
+ for rel, content in self.key_contents.items():
307
+ if budget <= 500:
308
+ break
309
+ snippet = content[:min(len(content), budget // max(1, len(self.key_contents)))]
310
+ block = f"\n--- {rel} ---\n{snippet}"
311
+ parts.append(block)
312
+ budget -= len(block)
313
+
314
+ # Tool capability hint
315
+ tool_hint = (
316
+ "\n--- 可用工具 ---\n"
317
+ "你可以调用以下工具来完成任务:\n"
318
+ " read_file(path) — 读取项目中任意文件\n"
319
+ " write_file(path, content) — 创建或覆写文件\n"
320
+ " edit_file(path, old, new) — 精确查找替换\n"
321
+ " search_code(pattern, path) — 跨文件正则搜索\n"
322
+ " list_files(path) — 列出目录内容\n"
323
+ " run_command(command, cwd) — 在项目目录执行 shell 命令\n"
324
+ "所有路径相对于项目根目录,或使用绝对路径。\n"
325
+ "执行任务时先规划步骤,再逐步调用工具完成。"
326
+ )
327
+ parts.append(tool_hint)
328
+
329
+ return "\n".join(parts)
330
+
331
+ # ── File reading (safe, within project root) ───────────────────────────────
332
+
333
+ def read_file(self, rel_or_abs: str, max_chars: int = 40_000) -> Tuple[bool, str]:
334
+ """Read a file within the project. Returns (ok, content_or_error)."""
335
+ p = Path(rel_or_abs)
336
+ if not p.is_absolute():
337
+ p = Path(self.root) / rel_or_abs
338
+ p = p.resolve()
339
+ root = Path(self.root).resolve()
340
+ if not str(p).startswith(str(root)):
341
+ return False, f"安全限制:路径 {p} 在项目目录之外"
342
+ if not p.exists():
343
+ return False, f"文件不存在: {p}"
344
+ if not p.is_file():
345
+ return False, f"不是文件: {p}"
346
+ try:
347
+ content = p.read_text(errors="replace")[:max_chars]
348
+ return True, content
349
+ except Exception as e:
350
+ return False, str(e)
351
+
352
+ # ── Grep ──────────────────────────────────────────────────────────────────
353
+
354
+ def grep(self, pattern: str, glob: str = "**/*",
355
+ max_results: int = 60) -> List[Dict[str, Any]]:
356
+ """Regex search across project files."""
357
+ results: List[Dict[str, Any]] = []
358
+ try:
359
+ rx = re.compile(pattern, re.IGNORECASE)
360
+ except re.error as e:
361
+ return [{"error": f"正则表达式错误: {e}"}]
362
+
363
+ root = Path(self.root)
364
+ for f in self.files:
365
+ if len(results) >= max_results:
366
+ break
367
+ if f.ext in _BINARY_EXTENSIONS or f.size > 2_000_000:
368
+ continue
369
+ if glob != "**/*":
370
+ if not fnmatch.fnmatch(f.rel_path, glob):
371
+ continue
372
+ try:
373
+ lines = Path(f.abs_path).read_text(errors="replace").splitlines()
374
+ for i, line in enumerate(lines, 1):
375
+ if rx.search(line):
376
+ results.append({
377
+ "file": f.rel_path,
378
+ "line": i,
379
+ "content": line.strip()[:200],
380
+ })
381
+ if len(results) >= max_results:
382
+ break
383
+ except Exception:
384
+ continue
385
+ return results
386
+
387
+ # ── Summary ───────────────────────────────────────────────────────────────
388
+
389
+ def summary(self) -> Dict[str, Any]:
390
+ lang_counts = self.stats.get("languages", {})
391
+ top_langs = sorted(lang_counts, key=lang_counts.get, reverse=True)[:5]
392
+ return {
393
+ "name": self.name,
394
+ "root": self.root,
395
+ "type": self.project_type,
396
+ "languages": top_langs,
397
+ "total_files": self.stats.get("total_files", 0),
398
+ "total_lines": self.stats.get("total_lines", 0),
399
+ "total_size_kb":self.stats.get("total_size_kb", 0),
400
+ "key_files": list(self.key_contents.keys()),
401
+ "git": self.git_info,
402
+ }
403
+
404
+
405
+ # ── Tree renderer ─────────────────────────────────────────────────────────────
406
+
407
+ def _render_tree(node: dict, lines: list, prefix: str, max_lines: int):
408
+ items = sorted(node.items(), key=lambda kv: (isinstance(kv[1], dict), kv[0]))
409
+ for i, (name, val) in enumerate(items):
410
+ if len(lines) >= max_lines:
411
+ return
412
+ is_last = (i == len(items) - 1)
413
+ connector = "└── " if is_last else "├── "
414
+ if isinstance(val, dict):
415
+ lines.append(f"{prefix}{connector}{name}/")
416
+ ext_prefix = prefix + (" " if is_last else "│ ")
417
+ _render_tree(val, lines, ext_prefix, max_lines)
418
+ else:
419
+ size_str = _fmt_size(val)
420
+ lines.append(f"{prefix}{connector}{name} [{size_str}]")
421
+
422
+
423
+ def _fmt_size(size: int) -> str:
424
+ if size < 1024: return f"{size}B"
425
+ if size < 1048576: return f"{size//1024}KB"
426
+ return f"{size//1048576}MB"
427
+
428
+
429
+ # ── Extension → language ──────────────────────────────────────────────────────
430
+
431
+ _EXT_LANG: Dict[str, str] = {
432
+ ".py":"Python", ".pyx":"Python", ".pyi":"Python",
433
+ ".js":"JavaScript", ".jsx":"JavaScript", ".mjs":"JavaScript",
434
+ ".ts":"TypeScript", ".tsx":"TypeScript",
435
+ ".go":"Go",
436
+ ".rs":"Rust",
437
+ ".java":"Java", ".kt":"Kotlin", ".kts":"Kotlin",
438
+ ".rb":"Ruby",
439
+ ".php":"PHP",
440
+ ".cs":"C#",
441
+ ".c":"C", ".h":"C", ".cpp":"C++", ".cc":"C++", ".hpp":"C++",
442
+ ".swift":"Swift",
443
+ ".dart":"Dart",
444
+ ".ex":"Elixir", ".exs":"Elixir",
445
+ ".html":"HTML", ".htm":"HTML",
446
+ ".css":"CSS", ".scss":"CSS", ".sass":"CSS", ".less":"CSS",
447
+ ".json":"JSON", ".jsonl":"JSON",
448
+ ".yaml":"YAML", ".yml":"YAML",
449
+ ".toml":"TOML",
450
+ ".md":"Markdown", ".mdx":"Markdown",
451
+ ".sh":"Shell", ".bash":"Shell", ".zsh":"Shell",
452
+ ".sql":"SQL",
453
+ ".tf":"Terraform", ".hcl":"Terraform",
454
+ ".proto":"Protobuf",
455
+ ".r":"R", ".R":"R",
456
+ ".lua":"Lua",
457
+ ".vim":"VimScript",
458
+ }
459
+
460
+ def _ext_to_lang(ext: str) -> str:
461
+ return _EXT_LANG.get(ext, "")
462
+
463
+
464
+ # ── Git integration ───────────────────────────────────────────────────────────
465
+
466
+ def _get_git_info(root: str) -> Dict[str, Any]:
467
+ info: Dict[str, Any] = {}
468
+ if not (Path(root) / ".git").exists():
469
+ return info
470
+
471
+ def _git(*args, capture=True) -> str:
472
+ try:
473
+ r = subprocess.run(
474
+ ["git", *args], cwd=root,
475
+ capture_output=capture, text=True, timeout=5
476
+ )
477
+ return r.stdout.strip() if r.returncode == 0 else ""
478
+ except Exception:
479
+ return ""
480
+
481
+ info["branch"] = _git("rev-parse", "--abbrev-ref", "HEAD")
482
+ info["remote"] = _git("remote", "get-url", "origin")
483
+ status_out = _git("status", "--short")
484
+ if status_out:
485
+ changed = [l for l in status_out.splitlines() if l.strip()]
486
+ info["changed_files"] = changed[:20]
487
+ info["changed_count"] = len(changed)
488
+ else:
489
+ info["changed_files"] = []
490
+ info["changed_count"] = 0
491
+ log_out = _git("log", "--oneline", "-8")
492
+ if log_out:
493
+ info["recent_commits"] = log_out.splitlines()
494
+ diff_stat = _git("diff", "--stat", "HEAD")
495
+ if diff_stat:
496
+ info["diff_stat"] = diff_stat[:800]
497
+ return info
498
+
499
+
500
+ # ── Standalone helpers (called by /project commands) ─────────────────────────
501
+
502
+ def scan_project(path: str, max_files: int = 2000) -> ProjectSession:
503
+ """Convenience: create + scan a new ProjectSession."""
504
+ s = ProjectSession()
505
+ s.scan(path, max_files=max_files)
506
+ return s
507
+
508
+
509
+ def format_grep_results(results: List[Dict[str, Any]],
510
+ pattern: str, max_show: int = 40) -> str:
511
+ """Format grep results for Rich console display."""
512
+ if not results:
513
+ return f'没有找到匹配 "{pattern}" 的内容'
514
+ if results and "error" in results[0]:
515
+ return results[0]["error"]
516
+ lines = [f'搜索 "{pattern}" — {len(results)} 个匹配\n']
517
+ cur_file = None
518
+ for r in results[:max_show]:
519
+ if r["file"] != cur_file:
520
+ cur_file = r["file"]
521
+ lines.append(f"\n 📄 {cur_file}")
522
+ lines.append(f" {r['line']:>4} │ {r['content']}")
523
+ if len(results) > max_show:
524
+ lines.append(f"\n … 还有 {len(results) - max_show} 个结果")
525
+ return "\n".join(lines)