erlangshen 0.1.0

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 (93) hide show
  1. package/.claude/agents/equity-agent.md +26 -0
  2. package/.claude/agents/macro-agent.md +25 -0
  3. package/.claude/commands/analyze.md +40 -0
  4. package/.claude/commands/macro.md +29 -0
  5. package/.claude/settings.json +12 -0
  6. package/CODEX_GOAL.md +46 -0
  7. package/README.md +206 -0
  8. package/bin/cli.js +67 -0
  9. package/bin/erlangshen +2 -0
  10. package/bin/xiaoergod +2 -0
  11. package/frontend/index.html +700 -0
  12. package/knowledge/crypto_guide.md +147 -0
  13. package/knowledge/economic_indicators.md +125 -0
  14. package/knowledge/financial_glossary.md +148 -0
  15. package/knowledge/first_principles.md +50 -0
  16. package/knowledge/first_principles_deep.md +115 -0
  17. package/knowledge/global_markets.md +173 -0
  18. package/knowledge/insights.md +141 -0
  19. package/knowledge/market_basics.md +116 -0
  20. package/knowledge/memos/session_20260513_003616.json +6 -0
  21. package/knowledge/memos/session_20260513_003822.json +6 -0
  22. package/knowledge/risk_management.md +151 -0
  23. package/knowledge/team_context.md +42 -0
  24. package/knowledge/trading_strategies.md +114 -0
  25. package/package.json +42 -0
  26. package/requirements.txt +14 -0
  27. package/scripts/postinstall.js +188 -0
  28. package/scripts/preuninstall.js +22 -0
  29. package/src/__init__.py +4 -0
  30. package/src/__pycache__/__init__.cpython-313.pyc +0 -0
  31. package/src/agents/__init__.py +3 -0
  32. package/src/agents/base.py +103 -0
  33. package/src/agents/base_agent.py +86 -0
  34. package/src/agents/equity.py +136 -0
  35. package/src/agents/equity_agent.py +91 -0
  36. package/src/agents/erlang.py +165 -0
  37. package/src/agents/macro.py +137 -0
  38. package/src/agents/macro_agent.py +81 -0
  39. package/src/agents/multi_asset.py +147 -0
  40. package/src/agents/multi_asset_agent.py +87 -0
  41. package/src/api/__init__.py +1 -0
  42. package/src/api/__pycache__/__init__.cpython-313.pyc +0 -0
  43. package/src/api/__pycache__/server.cpython-313.pyc +0 -0
  44. package/src/api/cli.py +435 -0
  45. package/src/api/cli_enhanced.py +537 -0
  46. package/src/api/server.py +266 -0
  47. package/src/brain.py +200 -0
  48. package/src/cli.py +153 -0
  49. package/src/commands/__init__.py +3 -0
  50. package/src/commands/analyze.py +131 -0
  51. package/src/commands/macro.py +100 -0
  52. package/src/commands/memo.py +216 -0
  53. package/src/commands/portfolio.py +154 -0
  54. package/src/commands/report.py +228 -0
  55. package/src/commands/risk.py +183 -0
  56. package/src/commands/search.py +183 -0
  57. package/src/commands/stock.py +124 -0
  58. package/src/config.py +327 -0
  59. package/src/core/__init__.py +1 -0
  60. package/src/core/brain.py +645 -0
  61. package/src/core/cerebellum.py +175 -0
  62. package/src/core/investment_universe.py +423 -0
  63. package/src/core/knowledge.py +207 -0
  64. package/src/core/memory.py +115 -0
  65. package/src/hooks/__init__.py +3 -0
  66. package/src/hooks/session_end.py +57 -0
  67. package/src/hooks/session_start.py +75 -0
  68. package/src/knowledge/__init__.py +1 -0
  69. package/src/mcp/__init__.py +3 -0
  70. package/src/mcp/feishu.py +331 -0
  71. package/src/mcp/fund_tools.py +323 -0
  72. package/src/mcp/macro.py +452 -0
  73. package/src/mcp/market.py +331 -0
  74. package/src/mcp/registry.py +168 -0
  75. package/src/network/__init__.py +15 -0
  76. package/src/network/detector.py +125 -0
  77. package/src/network/proxy.py +199 -0
  78. package/src/network/router.py +103 -0
  79. package/src/prompts/__init__.py +1 -0
  80. package/src/prompts/analysis_framework.md +164 -0
  81. package/src/prompts/persona.md +65 -0
  82. package/src/prompts/report_template.md +144 -0
  83. package/src/skills/__init__.py +3 -0
  84. package/src/skills/framework.py +105 -0
  85. package/src/skills/templates.py +342 -0
  86. package/src/tools/__init__.py +1 -0
  87. package/src/tools/file_tools.py +209 -0
  88. package/src/tools/macro_tools.py +152 -0
  89. package/src/tools/market_tools.py +1172 -0
  90. package/src/tools/registry.py +398 -0
  91. package/src/tools/search_tools.py +777 -0
  92. package/tests/__init__.py +1 -0
  93. package/tests/test_erlangshen.py +140 -0
@@ -0,0 +1 @@
1
+ """Tests"""
@@ -0,0 +1,140 @@
1
+ """
2
+ 测试套件 - 二郎神核心功能测试
3
+ """
4
+ import pytest
5
+ import asyncio
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
10
+
11
+ from src.core.brain import Brain
12
+ from src.core.memory import Memory
13
+ from src.core.knowledge import KnowledgeBase
14
+ from src.core.cerebellum import Cerebellum
15
+ from src.tools.market_tools import MarketTools
16
+ from src.tools.macro_tools import MacroTools
17
+ from src.tools.search_tools import SearchTools
18
+ from src.agents.erlang import 二郎神 as Erlangshen
19
+
20
+
21
+ @pytest.fixture
22
+ def brain():
23
+ return Brain()
24
+
25
+
26
+ @pytest.fixture
27
+ def memory():
28
+ return Memory()
29
+
30
+
31
+ @pytest.fixture
32
+ def knowledge(tmp_path):
33
+ return KnowledgeBase(base_path=str(tmp_path))
34
+
35
+
36
+ @pytest.fixture
37
+ def erlangshen(brain, memory, knowledge):
38
+ tools = {
39
+ "market_tools": MarketTools(),
40
+ "macro_tools": MacroTools(),
41
+ "search_tools": SearchTools(),
42
+ }
43
+ return Erlangshen(brain=brain, memory=memory, knowledge=knowledge, tools=tools)
44
+
45
+
46
+ class TestBrain:
47
+ def test_brain_init(self, brain):
48
+ assert brain.model is not None
49
+ assert brain.api_base is not None
50
+
51
+ @pytest.mark.asyncio
52
+ async def test_think(self, brain):
53
+ result = await brain.think("你好,请用一句话介绍自己")
54
+ assert isinstance(result, str)
55
+ assert len(result) > 0
56
+
57
+ @pytest.mark.asyncio
58
+ async def test_analyze(self, brain):
59
+ result = await brain.analyze("分析当前全球经济形势")
60
+ assert result.conclusion is not None
61
+ assert 0 <= result.confidence <= 1
62
+
63
+
64
+ class TestMemory:
65
+ @pytest.mark.asyncio
66
+ async def test_add_message(self, memory):
67
+ await memory.add_message("user", "Hello")
68
+ context = await memory.get_context()
69
+ assert len(context) == 1
70
+ assert context[0].content == "Hello"
71
+
72
+ @pytest.mark.asyncio
73
+ async def test_add_interaction(self, memory):
74
+ await memory.add_interaction("Query", "Response")
75
+ events = await memory.get_recent_events(hours=1)
76
+ assert len(events) >= 1
77
+
78
+ @pytest.mark.asyncio
79
+ async def test_register_skill(self, memory):
80
+ async def dummy_skill():
81
+ return "done"
82
+ memory.register_skill("dummy", dummy_skill)
83
+ skill = memory.get_skill("dummy")
84
+ assert skill is not None
85
+
86
+
87
+ class TestKnowledgeBase:
88
+ @pytest.mark.asyncio
89
+ async def test_add_entry(self, knowledge):
90
+ entry = knowledge.add("Test knowledge", category="test")
91
+ assert entry.entry_id is not None
92
+ assert entry.content == "Test knowledge"
93
+
94
+ @pytest.mark.asyncio
95
+ async def test_search(self, knowledge):
96
+ knowledge.add("茅台是高端白酒", category="stock")
97
+ results = await knowledge.search("茅台", top_k=5)
98
+ assert len(results) >= 1
99
+
100
+
101
+ class TestMarketTools:
102
+ @pytest.mark.asyncio
103
+ async def test_get_stock_price(self):
104
+ tools = MarketTools()
105
+ result = await tools.get_stock_price("600519")
106
+ assert "symbol" in result
107
+ assert result["symbol"] == "600519"
108
+
109
+
110
+ class TestMacroTools:
111
+ @pytest.mark.asyncio
112
+ async def test_get_interest_rates(self):
113
+ tools = MacroTools()
114
+ result = await tools.get_interest_rates("CN")
115
+ assert "rates" in result
116
+ assert "CN" in result["country"]
117
+
118
+
119
+ class TestErlangshen:
120
+ @pytest.mark.asyncio
121
+ async def test_classify_query(self, erlangshen):
122
+ assert erlangshen._classify_query("分析茅台股票") == "equity"
123
+ assert erlangshen._classify_query("分析宏观经济") == "macro"
124
+ assert erlangshen._classify_query("资产配置建议") == "multi_asset"
125
+
126
+ @pytest.mark.asyncio
127
+ async def test_process(self, erlangshen):
128
+ result = await erlangshen.process("分析当前A股市场")
129
+ assert "query" in result
130
+ assert "erlangshen_insight" in result
131
+
132
+ @pytest.mark.asyncio
133
+ async def test_analyze_stock(self, erlangshen):
134
+ result = await erlangshen.analyze_stock("600519")
135
+ assert "query" in result
136
+ assert result["symbol"] == "600519"
137
+
138
+
139
+ if __name__ == "__main__":
140
+ pytest.main([__file__, "-v"])