feihong-code 8.0.0 → 8.0.2
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.
- package/.github/workflows/ci.yml +193 -193
- package/CHANGELOG.md +140 -117
- package/README.md +656 -636
- package/agent-team/.env.example +13 -0
- package/agent-team/README.md +42 -0
- package/agent-team/agents/__init__.py +0 -0
- package/agent-team/agents/l1_acquisition.py +207 -0
- package/agent-team/agents/l2_content.py +237 -0
- package/agent-team/agents/l3_conversion.py +148 -0
- package/agent-team/agents/l4_analysis.py +118 -0
- package/agent-team/agents/l5_management.py +52 -0
- package/agent-team/agents/registry.py +60 -0
- package/agent-team/config.py +39 -0
- package/agent-team/core/__init__.py +0 -0
- package/agent-team/core/agent.py +73 -0
- package/agent-team/core/models.py +347 -0
- package/agent-team/core/scheduler.py +150 -0
- package/agent-team/core/task.py +121 -0
- package/agent-team/feihongzhi.db +0 -0
- package/agent-team/llm/__init__.py +12 -0
- package/agent-team/llm/base.py +22 -0
- package/agent-team/llm/doubao_llm.py +52 -0
- package/agent-team/llm/mock_llm.py +42 -0
- package/agent-team/main.py +235 -0
- package/agent-team/requirements.txt +2 -0
- package/agent-team/skill_packager.py +248 -0
- package/agent-team/skills/01_AI/350/216/267/345/256/242/347/272/277/347/264/242/351/233/267/350/276/276/SKILL.md +40 -0
- package/agent-team/skills/01_AI/350/216/267/345/256/242/347/272/277/347/264/242/351/233/267/350/276/276/run.py +111 -0
- package/agent-team/skills/02_AI/351/224/200/345/224/256/350/267/237/350/277/233/351/224/200/345/206/240/SKILL.md +38 -0
- package/agent-team/skills/02_AI/351/224/200/345/224/256/350/267/237/350/277/233/351/224/200/345/206/240/run.py +108 -0
- package/agent-team/skills/03_/350/257/204/350/256/272/345/214/272/345/225/206/346/234/272/350/257/206/345/210/253/345/256/230/SKILL.md +38 -0
- package/agent-team/skills/03_/350/257/204/350/256/272/345/214/272/345/225/206/346/234/272/350/257/206/345/210/253/345/256/230/run.py +106 -0
- package/agent-team/skills/04_/345/256/242/346/210/267/350/201/212/345/244/251/346/210/220/344/272/244/345/210/206/346/236/220/345/256/230/SKILL.md +37 -0
- package/agent-team/skills/04_/345/256/242/346/210/267/350/201/212/345/244/251/346/210/220/344/272/244/345/210/206/346/236/220/345/256/230/run.py +107 -0
- package/agent-team/skills/05_/345/220/214/350/241/214/347/210/206/346/254/276/351/233/267/350/276/276/SKILL.md +38 -0
- package/agent-team/skills/05_/345/220/214/350/241/214/347/210/206/346/254/276/351/233/267/350/276/276/run.py +99 -0
- package/agent-team/skills/06_/346/257/217/346/227/245/347/262/276/345/207/206/350/216/267/345/256/242/351/200/211/351/242/230/345/256/230/SKILL.md +39 -0
- package/agent-team/skills/06_/346/257/217/346/227/245/347/262/276/345/207/206/350/216/267/345/256/242/351/200/211/351/242/230/345/256/230/run.py +103 -0
- package/agent-team/skills/07_AI/345/244/226/350/264/270/345/274/200/345/217/221/345/256/242/346/210/267/345/221/230/345/267/245/SKILL.md +39 -0
- package/agent-team/skills/07_AI/345/244/226/350/264/270/345/274/200/345/217/221/345/256/242/346/210/267/345/221/230/345/267/245/run.py +103 -0
- package/agent-team/skills/08_/345/260/217/347/272/242/344/271/246/347/262/276/345/207/206/350/216/267/345/256/242/345/221/230/345/267/245/SKILL.md +40 -0
- package/agent-team/skills/08_/345/260/217/347/272/242/344/271/246/347/262/276/345/207/206/350/216/267/345/256/242/345/221/230/345/267/245/run.py +97 -0
- package/agent-team/skills/09_/347/247/201/345/237/237/345/256/242/346/210/267/345/210/206/345/261/202/350/267/237/350/277/233/345/256/230/SKILL.md +38 -0
- package/agent-team/skills/09_/347/247/201/345/237/237/345/256/242/346/210/267/345/210/206/345/261/202/350/267/237/350/277/233/345/256/230/run.py +106 -0
- package/agent-team/skills/10_GEO/345/225/206/346/234/272/350/257/212/346/226/255/345/256/230/SKILL.md +38 -0
- package/agent-team/skills/10_GEO/345/225/206/346/234/272/350/257/212/346/226/255/345/256/230/run.py +108 -0
- package/agent-team/skills/11_/344/270/200/344/272/272/345/205/254/345/217/270AI/345/221/230/345/267/245/350/260/203/345/272/246/345/256/230/SKILL.md +37 -0
- package/agent-team/skills/11_/344/270/200/344/272/272/345/205/254/345/217/270AI/345/221/230/345/267/245/350/260/203/345/272/246/345/256/230/run.py +111 -0
- package/agent-team/skills/12_/350/200/201/346/235/277/347/237/255/350/247/206/351/242/221/350/216/267/345/256/242/350/204/232/346/234/254/345/256/230/SKILL.md +39 -0
- package/agent-team/skills/12_/350/200/201/346/235/277/347/237/255/350/247/206/351/242/221/350/216/267/345/256/242/350/204/232/346/234/254/345/256/230/run.py +104 -0
- package/agent-team/skills/13_/345/215/232/344/270/273/350/264/246/345/217/267/346/267/261/345/272/246/346/213/206/350/247/243/345/256/230/SKILL.md +37 -0
- package/agent-team/skills/13_/345/215/232/344/270/273/350/264/246/345/217/267/346/267/261/345/272/246/346/213/206/350/247/243/345/256/230/run.py +105 -0
- package/agent-team/skills/14_AI/347/237/255/350/247/206/351/242/221/350/207/252/345/212/250/345/211/252/350/276/221/345/270/210/SKILL.md +39 -0
- package/agent-team/skills/14_AI/347/237/255/350/247/206/351/242/221/350/207/252/345/212/250/345/211/252/350/276/221/345/270/210/run.py +108 -0
- package/agent-team/skills/15_/345/205/254/344/274/227/345/217/267/350/207/252/345/212/250/350/277/220/350/220/245/345/217/221/345/270/203/345/256/230/SKILL.md +38 -0
- package/agent-team/skills/15_/345/205/254/344/274/227/345/217/267/350/207/252/345/212/250/350/277/220/350/220/245/345/217/221/345/270/203/345/256/230/run.py +105 -0
- package/agent-team/skills/16_/350/241/214/344/270/232/346/267/261/345/272/246/345/210/206/346/236/220/345/270/210/SKILL.md +38 -0
- package/agent-team/skills/16_/350/241/214/344/270/232/346/267/261/345/272/246/345/210/206/346/236/220/345/270/210/run.py +108 -0
- package/agent-team/skills/17_/346/212/225/350/265/204/347/240/224/347/251/266/345/222/250/350/257/242/345/256/230/SKILL.md +38 -0
- package/agent-team/skills/17_/346/212/225/350/265/204/347/240/224/347/251/266/345/222/250/350/257/242/345/256/230/run.py +106 -0
- package/agent-team/tests/__init__.py +0 -0
- package/agent-team/tests/test_core.py +156 -0
- package/dist/agent/agent-session.js +103 -0
- package/dist/agent/agent-session.js.map +1 -0
- package/dist/agent/orchestrator.js +8 -0
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/steer.js +52 -0
- package/dist/agent/steer.js.map +1 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/node-guard.js +17 -0
- package/dist/cli/node-guard.js.map +1 -0
- package/dist/cli/run.js +2 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/version.js +1 -1
- package/dist/enterprise/policy.js +40 -17
- package/dist/enterprise/policy.js.map +1 -1
- package/dist/tools/agents/agents-bridge.js +144 -0
- package/dist/tools/agents/agents-bridge.js.map +1 -0
- package/dist/tools/desktop/desktop-guard.js +81 -0
- package/dist/tools/desktop/desktop-guard.js.map +1 -0
- package/dist/tools/desktop/desktop.tool.js +201 -0
- package/dist/tools/desktop/desktop.tool.js.map +1 -0
- package/dist/tools/desktop/feihong-win.js +163 -0
- package/dist/tools/desktop/feihong-win.js.map +1 -0
- package/dist/tools/desktop/index.js +37 -0
- package/dist/tools/desktop/index.js.map +1 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp/index.js +10 -2
- package/dist/tools/mcp/index.js.map +1 -1
- package/dist/tools/mcp/mcp-client.js +4 -0
- package/dist/tools/mcp/mcp-client.js.map +1 -1
- package/dist/tools/sandbox.js +28 -0
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/web/public/public/css/style.css +1756 -0
- package/dist/web/public/public/favicon.svg +11 -0
- package/dist/web/public/public/index.html +1246 -0
- package/dist/web/public/public/js/api.js +558 -0
- package/dist/web/public/public/js/app.js +2233 -0
- package/dist/web/public/public/js/mock-api.js +259 -0
- package/dist/web/public/public/js/monaco-editor.js +363 -0
- package/dist/web/public/public/js/ui.js +2217 -0
- package/dist/web/public/public/js/utils.js +214 -0
- package/dist/web/public/public/manifest.json +59 -0
- package/dist/web/public/public/robots.txt +14 -0
- package/dist/web/public/public/service-worker.js +149 -0
- package/docs/AI/345/221/230/345/267/245/345/206/233/345/233/242-/346/225/264/345/220/210/350/257/264/346/230/216.md +68 -0
- package/docs/API.md +1 -1
- package/docs/App/346/212/200/346/234/257/350/257/264/346/230/216/344/271/246.md +3 -3
- package/docs/P1.1-P3-P5/345/267/245/347/250/213/345/256/236/346/226/275/346/200/273/347/273/223.md +328 -0
- package/docs/P5-Pi/345/257/271/347/205/247/350/257/204/346/265/213/346/212/245/345/221/212-mock/346/250/241/345/274/217.json +125 -0
- package/docs/P5-Pi/345/257/271/347/205/247/350/257/204/346/265/213/346/212/245/345/221/212-/347/234/237/345/256/236/346/250/241/345/236/213.json +138 -0
- package/docs/P5-pi-compare-real-report.json +138 -0
- package/docs/P5-pi-compare-report.json +125 -0
- package/docs/Pi-Agent/346/216/245/345/205/245/351/243/236/350/231/271Code-MVP/351/233/206/346/210/220/344/272/244/344/273/230/347/211/251.md +355 -0
- package/docs/Pi-Agent/346/216/245/345/205/245/351/243/236/350/231/271Code/344/273/267/345/200/274/345/210/206/346/236/220-/345/274/200/345/217/221/346/226/207/346/241/243.md +291 -0
- package/docs/Pi-Agent/346/216/245/345/205/245/351/243/236/350/231/271Code/344/273/267/345/200/274/351/207/215/344/274/260-/345/217/257/350/247/206/345/214/226.html +84 -0
- package/docs/SWE-bench-300-agnes-2.5-flash-/346/234/200/347/273/210/346/212/245/345/221/212.json +2012 -0
- package/docs/SWE-bench-300-agnes-2.5-flash-/350/267/221/345/210/206/346/212/245/345/221/212.md +74 -0
- package/docs/SWE-bench-Lite-DeepSeek-V4-Flash-/350/267/221/345/210/206/346/212/245/345/221/212.md +102 -0
- package/docs/TECHNICAL-SPECIFICATION.md +66 -0
- package/docs/TECHNICAL-SPECIFICATION.pdf +0 -0
- package/docs/Windows/346/211/213/350/204/232-POC/346/274/224/347/244/272/350/204/232/346/234/254.md +131 -0
- package/docs/Windows/346/211/213/350/204/232/346/216/245/345/205/245/346/214/207/345/215/227.md +181 -0
- package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246-v8.0.1.md +146 -0
- package/docs//344/275/277/347/224/250/350/257/264/346/230/216/344/271/246.md +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""L4 分析决策层:10 GEO商机诊断官 / 16 行业深度分析师 / 17 投资研究咨询官。"""
|
|
2
|
+
import json
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from core.agent import BaseAgent
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _ts() -> str:
|
|
9
|
+
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ---------------------------------------------------------------- 10
|
|
13
|
+
def run_logic_10(data, llm=None):
|
|
14
|
+
"""GEO 商机诊断:基于地理与经营数据诊断潜在商机。"""
|
|
15
|
+
region = data.get("region", "泉州")
|
|
16
|
+
business = data.get("business_type", "企业服务")
|
|
17
|
+
diagnosis = {
|
|
18
|
+
"region": region,
|
|
19
|
+
"business_type": business,
|
|
20
|
+
"zones": [
|
|
21
|
+
{"zone": f"{region}·核心商圈", "score": 92, "reason": "人口密度高、企业密集"},
|
|
22
|
+
{"zone": f"{region}·产业园区", "score": 85, "reason": "目标客群集中"},
|
|
23
|
+
],
|
|
24
|
+
"priority": "建议优先覆盖核心商圈",
|
|
25
|
+
"diagnosed_at": _ts(),
|
|
26
|
+
}
|
|
27
|
+
ai_note = ""
|
|
28
|
+
if llm is not None and getattr(llm, "provider", "mock") != "mock":
|
|
29
|
+
try:
|
|
30
|
+
ai_note = llm.complete(
|
|
31
|
+
f"区域 {region}、业态 {business},给出获客优先级判断,不超过 60 字。",
|
|
32
|
+
system="你是 GEO 商业诊断专家。")
|
|
33
|
+
except Exception:
|
|
34
|
+
ai_note = ""
|
|
35
|
+
return {"diagnosis": diagnosis, "ai_note": ai_note}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class GeoDiagnosisAgent(BaseAgent):
|
|
39
|
+
module_id = "10"
|
|
40
|
+
name = "GEO商机诊断官"
|
|
41
|
+
layer = "L4"
|
|
42
|
+
priority = "P3"
|
|
43
|
+
description = "基于地理与经营数据诊断潜在商机"
|
|
44
|
+
input_schema = {"region": "目标区域", "business_type": "业态"}
|
|
45
|
+
output_keys = {"diagnosis": "商机诊断报告"}
|
|
46
|
+
run_logic = staticmethod(run_logic_10)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# ---------------------------------------------------------------- 16
|
|
50
|
+
def run_logic_16(data, llm=None):
|
|
51
|
+
"""行业深度分析:输出行业趋势与竞争格局。"""
|
|
52
|
+
industry = data.get("industry", "企业服务")
|
|
53
|
+
scope = data.get("scope", "国内")
|
|
54
|
+
report = {
|
|
55
|
+
"industry": industry,
|
|
56
|
+
"scope": scope,
|
|
57
|
+
"market_size": "示例口径:120 亿元(需以权威数据源校准)",
|
|
58
|
+
"growth": "年增速约 18%",
|
|
59
|
+
"competition": "格局分散,头部集中度提升中",
|
|
60
|
+
"conclusion": "进入窗口期,建议聚焦细分场景建立壁垒",
|
|
61
|
+
"data_note": "本报告为分析框架示意,关键数据需接入权威数据源后校准",
|
|
62
|
+
"generated_at": _ts(),
|
|
63
|
+
}
|
|
64
|
+
ai_note = ""
|
|
65
|
+
if llm is not None and getattr(llm, "provider", "mock") != "mock":
|
|
66
|
+
try:
|
|
67
|
+
ai_note = llm.complete(
|
|
68
|
+
f"行业 {industry}、范围 {scope},给 1 条最关键的竞争判断,不超过 60 字。",
|
|
69
|
+
system="你是行业研究首席分析师。")
|
|
70
|
+
except Exception:
|
|
71
|
+
ai_note = ""
|
|
72
|
+
return {"report": report, "ai_note": ai_note}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class IndustryAnalystAgent(BaseAgent):
|
|
76
|
+
module_id = "16"
|
|
77
|
+
name = "行业深度分析师"
|
|
78
|
+
layer = "L4"
|
|
79
|
+
priority = "P3"
|
|
80
|
+
description = "输出行业趋势与竞争格局分析"
|
|
81
|
+
input_schema = {"industry": "行业", "scope": "范围"}
|
|
82
|
+
output_keys = {"report": "行业分析报告"}
|
|
83
|
+
run_logic = staticmethod(run_logic_16)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# ---------------------------------------------------------------- 17
|
|
87
|
+
def run_logic_17(data, llm=None):
|
|
88
|
+
"""投资研究:项目 / 投资研究与尽调辅助。"""
|
|
89
|
+
company = data.get("company", "示例项目")
|
|
90
|
+
materials = data.get("materials", "BP 摘要")
|
|
91
|
+
report = {
|
|
92
|
+
"company": company,
|
|
93
|
+
"business_model": "B2B 订阅 + 增值服务",
|
|
94
|
+
"risks": ["获客成本偏高", "复购率待验证"],
|
|
95
|
+
"valuation_notes": "建议以 DCF + 可比公司交叉验证(需财务数据支撑)",
|
|
96
|
+
"conclusion": "方向成立,需补充现金流与复购数据后再决策",
|
|
97
|
+
"generated_at": _ts(),
|
|
98
|
+
}
|
|
99
|
+
ai_note = ""
|
|
100
|
+
if llm is not None and getattr(llm, "provider", "mock") != "mock":
|
|
101
|
+
try:
|
|
102
|
+
ai_note = llm.complete(
|
|
103
|
+
f"项目 {company}、材料 {materials[:100]},提示最需要核实的一个风险点,不超过 50 字。",
|
|
104
|
+
system="你是投资研究顾问。")
|
|
105
|
+
except Exception:
|
|
106
|
+
ai_note = ""
|
|
107
|
+
return {"report": report, "ai_note": ai_note}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class InvestResearchAgent(BaseAgent):
|
|
111
|
+
module_id = "17"
|
|
112
|
+
name = "投资研究咨询官"
|
|
113
|
+
layer = "L4"
|
|
114
|
+
priority = "P3"
|
|
115
|
+
description = "项目 / 投资研究与尽调辅助"
|
|
116
|
+
input_schema = {"company": "项目/公司", "materials": "材料摘要"}
|
|
117
|
+
output_keys = {"report": "投研报告"}
|
|
118
|
+
run_logic = staticmethod(run_logic_17)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""L5 系统管理层:11 一人公司 AI 员工调度官。
|
|
2
|
+
|
|
3
|
+
调度官的运行骨架在 core/scheduler.py;此处注册为可编排模块,
|
|
4
|
+
提供「调度计划生成」能力(供其他模块/智能体调用),并声明系统级元信息。
|
|
5
|
+
"""
|
|
6
|
+
import json
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
from core.agent import BaseAgent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _ts() -> str:
|
|
13
|
+
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def run_logic_11(data, llm=None):
|
|
17
|
+
"""调度计划:按优先级与依赖生成执行顺序。"""
|
|
18
|
+
tasks = data.get("tasks") or [
|
|
19
|
+
{"module_id": "01", "task_type": "lead_scan", "priority": "P0"},
|
|
20
|
+
{"module_id": "02", "task_type": "follow_up", "priority": "P0"},
|
|
21
|
+
{"module_id": "04", "task_type": "chat_analysis", "priority": "P0"},
|
|
22
|
+
{"module_id": "09", "task_type": "tiering", "priority": "P0"},
|
|
23
|
+
]
|
|
24
|
+
order = sorted(tasks, key=lambda t: {"P0": 0, "P1": 1, "P2": 2, "P3": 3}.get(t.get("priority", "P1"), 1))
|
|
25
|
+
schedule = {
|
|
26
|
+
"order": [t["module_id"] for t in order],
|
|
27
|
+
"dependency_rule": "前置任务 success 后触发后续任务",
|
|
28
|
+
"retry_policy": "失败自动重试,上限 3 次,超限转 blocked 并告警",
|
|
29
|
+
"human_gate": "涉及对外触达的任务在人工确认节点暂停",
|
|
30
|
+
"estimated_minutes": len(order) * 3,
|
|
31
|
+
"planned_at": _ts(),
|
|
32
|
+
}
|
|
33
|
+
ai_note = ""
|
|
34
|
+
if llm is not None and getattr(llm, "provider", "mock") != "mock":
|
|
35
|
+
try:
|
|
36
|
+
ai_note = llm.complete(
|
|
37
|
+
f"任务列表 {json.dumps(tasks, ensure_ascii=False)},指出编排上的一个风险,不超过 50 字。",
|
|
38
|
+
system="你是系统调度架构师。")
|
|
39
|
+
except Exception:
|
|
40
|
+
ai_note = ""
|
|
41
|
+
return {"schedule": schedule, "ai_note": ai_note}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class DispatcherAgent(BaseAgent):
|
|
45
|
+
module_id = "11"
|
|
46
|
+
name = "一人公司AI员工调度官"
|
|
47
|
+
layer = "L5"
|
|
48
|
+
priority = "基建"
|
|
49
|
+
description = "编排、调度、监控全部 AI 员工,管理任务全生命周期"
|
|
50
|
+
input_schema = {"tasks": "待编排任务列表"}
|
|
51
|
+
output_keys = {"schedule": "执行顺序与策略"}
|
|
52
|
+
run_logic = staticmethod(run_logic_11)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""模块注册表:集中注册 17 个 AI 员工,支持按 module_id 查询与实例化。"""
|
|
2
|
+
from typing import Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
from core.agent import BaseAgent
|
|
5
|
+
|
|
6
|
+
from agents.l1_acquisition import (
|
|
7
|
+
CommentOpportunityAgent, DailyTopicAgent, ForeignTradeAgent,
|
|
8
|
+
LeadRadarAgent, XiaohongshuAgent,
|
|
9
|
+
)
|
|
10
|
+
from agents.l2_content import (
|
|
11
|
+
AutoEditorAgent, BloggerTeardownAgent, GzhPublisherAgent,
|
|
12
|
+
VideoScriptAgent, ViralRadarAgent,
|
|
13
|
+
)
|
|
14
|
+
from agents.l3_conversion import ChatAnalysisAgent, FollowUpAgent, TieringAgent
|
|
15
|
+
from agents.l4_analysis import GeoDiagnosisAgent, IndustryAnalystAgent, InvestResearchAgent
|
|
16
|
+
from agents.l5_management import DispatcherAgent
|
|
17
|
+
|
|
18
|
+
# 模块类注册表(顺序即展示顺序)
|
|
19
|
+
AGENT_CLASSES: List[type] = [
|
|
20
|
+
LeadRadarAgent, # 01
|
|
21
|
+
FollowUpAgent, # 02
|
|
22
|
+
CommentOpportunityAgent, # 03
|
|
23
|
+
ChatAnalysisAgent, # 04
|
|
24
|
+
ViralRadarAgent, # 05
|
|
25
|
+
DailyTopicAgent, # 06
|
|
26
|
+
ForeignTradeAgent, # 07
|
|
27
|
+
XiaohongshuAgent, # 08
|
|
28
|
+
TieringAgent, # 09
|
|
29
|
+
GeoDiagnosisAgent, # 10
|
|
30
|
+
DispatcherAgent, # 11
|
|
31
|
+
VideoScriptAgent, # 12
|
|
32
|
+
BloggerTeardownAgent, # 13
|
|
33
|
+
AutoEditorAgent, # 14
|
|
34
|
+
GzhPublisherAgent, # 15
|
|
35
|
+
IndustryAnalystAgent, # 16
|
|
36
|
+
InvestResearchAgent, # 17
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_agent_classes() -> List[type]:
|
|
41
|
+
return list(AGENT_CLASSES)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def find_agent_class(module_id: str) -> Optional[type]:
|
|
45
|
+
for cls in AGENT_CLASSES:
|
|
46
|
+
if cls.module_id == module_id:
|
|
47
|
+
return cls
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def instantiate_all(llm) -> Dict[str, BaseAgent]:
|
|
52
|
+
"""实例化全部模块(注入同一 LLM 客户端)。"""
|
|
53
|
+
agents: Dict[str, BaseAgent] = {}
|
|
54
|
+
for cls in AGENT_CLASSES:
|
|
55
|
+
agents[cls.module_id] = cls(llm=llm)
|
|
56
|
+
return agents
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def list_meta() -> List[Dict]:
|
|
60
|
+
return [cls(llm=None).meta() for cls in AGENT_CLASSES]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""全局配置:从环境变量与 .env 文件读取,禁止硬编码密钥。
|
|
2
|
+
|
|
3
|
+
- LLM_PROVIDER=mock 无 API Key 时用本地确定性 mock,跑通全链路
|
|
4
|
+
- LLM_PROVIDER=doubao 接入豆包大模型(需配置 DOUBAO_API_KEY / DOUBAO_MODEL)
|
|
5
|
+
"""
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
BASE_DIR = Path(__file__).resolve().parent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _load_dotenv(path: Path) -> None:
|
|
13
|
+
"""极简 .env 加载器(KEY=VALUE,忽略 # 注释与空行)。"""
|
|
14
|
+
if not path.exists():
|
|
15
|
+
return
|
|
16
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
17
|
+
line = line.strip()
|
|
18
|
+
if not line or line.startswith("#") or "=" not in line:
|
|
19
|
+
continue
|
|
20
|
+
key, _, value = line.partition("=")
|
|
21
|
+
key, value = key.strip(), value.strip().strip('"').strip("'")
|
|
22
|
+
if key and key not in os.environ:
|
|
23
|
+
os.environ[key] = value
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
_load_dotenv(BASE_DIR / ".env")
|
|
27
|
+
|
|
28
|
+
# 数据存储
|
|
29
|
+
DB_PATH = os.getenv("DB_PATH", str(BASE_DIR / "feihongzhi.db"))
|
|
30
|
+
|
|
31
|
+
# LLM
|
|
32
|
+
LLM_PROVIDER = os.getenv("LLM_PROVIDER", "mock") # mock | doubao
|
|
33
|
+
DOUBAO_API_KEY = os.getenv("DOUBAO_API_KEY", "")
|
|
34
|
+
DOUBAO_MODEL = os.getenv("DOUBAO_MODEL", "doubao-seed-1-6-250615")
|
|
35
|
+
DOUBAO_BASE_URL = os.getenv("DOUBAO_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3")
|
|
36
|
+
|
|
37
|
+
# 调度
|
|
38
|
+
MAX_RETRY = int(os.getenv("MAX_RETRY", "3")) # 失败重试上限
|
|
39
|
+
ALERT_LEVEL = os.getenv("ALERT_LEVEL", "log") # log | stdout
|
|
File without changes
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""BaseAgent:所有 AI 员工模块的基类。
|
|
2
|
+
|
|
3
|
+
设计要点(支持 Skill 单独分发):
|
|
4
|
+
- 每个模块的核心业务逻辑写在模块级纯函数 run_logic(input_data, llm) 中,
|
|
5
|
+
不依赖类实例与数据库,可被 skill_packager 用 inspect.getsource 内嵌导出为独立 run.py。
|
|
6
|
+
- BaseAgent 负责:契约校验(输入/输出 schema)、trace 记录、LLM 注入、错误上抛。
|
|
7
|
+
"""
|
|
8
|
+
from typing import Any, Callable, Dict, Optional
|
|
9
|
+
|
|
10
|
+
from core.task import Task, TaskError
|
|
11
|
+
|
|
12
|
+
# 简化 JSON Schema:字段名 -> 描述/约束
|
|
13
|
+
EMPTY_SCHEMA: Dict[str, Any] = {}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseAgent:
|
|
17
|
+
module_id: str = ""
|
|
18
|
+
name: str = ""
|
|
19
|
+
layer: str = ""
|
|
20
|
+
priority: str = "P1" # P0 | P1 | P2 | P3 | 基建
|
|
21
|
+
description: str = ""
|
|
22
|
+
input_schema: Dict[str, str] = EMPTY_SCHEMA # 必填字段: 说明
|
|
23
|
+
output_keys: Dict[str, str] = EMPTY_SCHEMA # 输出字段: 说明
|
|
24
|
+
need_human: bool = False # 是否需人工确认
|
|
25
|
+
run_logic: Callable[[Dict[str, Any], Any], Dict[str, Any]] = staticmethod(
|
|
26
|
+
lambda data, llm: {"result": data}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def __init__(self, llm: Optional[Any] = None):
|
|
30
|
+
self.llm = llm
|
|
31
|
+
|
|
32
|
+
# ------------------------------------------------------------------
|
|
33
|
+
def validate_input(self, data: Any) -> Dict[str, Any]:
|
|
34
|
+
if not isinstance(data, dict):
|
|
35
|
+
raise TaskError(f"[{self.module_id}] 输入必须是 JSON 对象,收到 {type(data).__name__}")
|
|
36
|
+
for field, desc in self.input_schema.items():
|
|
37
|
+
if field not in data:
|
|
38
|
+
raise TaskError(f"[{self.module_id}] 缺少必填输入字段 {field}({desc})")
|
|
39
|
+
return data
|
|
40
|
+
|
|
41
|
+
def validate_output(self, output: Any) -> Dict[str, Any]:
|
|
42
|
+
if not isinstance(output, dict):
|
|
43
|
+
raise TaskError(f"[{self.module_id}] 输出必须是 JSON 对象,收到 {type(output).__name__}")
|
|
44
|
+
return output
|
|
45
|
+
|
|
46
|
+
# ------------------------------------------------------------------
|
|
47
|
+
def execute(self, task: Task) -> Dict[str, Any]:
|
|
48
|
+
"""调度官调用入口:契约校验 -> 纯函数执行 -> 输出校验 -> trace。"""
|
|
49
|
+
data = self.validate_input(task.input_json)
|
|
50
|
+
task.append_trace("validate_input", "ok")
|
|
51
|
+
output = self.run_logic(data, self.llm)
|
|
52
|
+
output = self.validate_output(output)
|
|
53
|
+
task.append_trace("run_logic", f"output_keys={sorted(output.keys())}")
|
|
54
|
+
return output
|
|
55
|
+
|
|
56
|
+
def persist(self, output: Dict[str, Any], task: Task) -> None:
|
|
57
|
+
"""可选持久化钩子:模块结果落库(leads/customers/content_assets)。
|
|
58
|
+
|
|
59
|
+
仅主系统调度时调用;Skill 分发版 run.py 保持纯逻辑,由调用方决定落库。
|
|
60
|
+
"""
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
def meta(self) -> Dict[str, Any]:
|
|
64
|
+
return {
|
|
65
|
+
"module_id": self.module_id,
|
|
66
|
+
"name": self.name,
|
|
67
|
+
"layer": self.layer,
|
|
68
|
+
"priority": self.priority,
|
|
69
|
+
"description": self.description,
|
|
70
|
+
"input_schema": self.input_schema,
|
|
71
|
+
"output_keys": self.output_keys,
|
|
72
|
+
"need_human": self.need_human,
|
|
73
|
+
}
|