mcp_llm-debate 1.0.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.
- package/SERVER_METADATA.json +6 -0
- package/graphs/brainstorming.json +50 -0
- package/graphs/classic-debate.json +54 -0
- package/graphs/panel-discussion.json +55 -0
- package/graphs/socratic-dialogue.json +51 -0
- package/package.json +58 -0
- package/src/cli.js +146 -0
- package/src/config.js +62 -0
- package/src/debate-engine.js +218 -0
- package/src/graph-loader.js +95 -0
- package/src/index.js +306 -0
- package/src/lib.js +45 -0
- package/src/llm-client.js +62 -0
- package/src/session-manager.js +101 -0
- package/src/transports/http.js +99 -0
- package/src/transports/rest.js +167 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "brainstorming",
|
|
3
|
+
"description": "头脑风暴模式:多角色自由发散,产生创意和灵感",
|
|
4
|
+
"roles": [
|
|
5
|
+
{
|
|
6
|
+
"name": "facilitator",
|
|
7
|
+
"persona": "你是引导者,负责提出头脑风暴的主题和方向。鼓励大家大胆提出想法,不做评判。记录有价值的创意,引导讨论走向深入。确保每个人都有发言机会。"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"name": "visionary",
|
|
11
|
+
"persona": "你是远见者,思维方式天马行空。你擅长提出大胆的、颠覆性的想法,不受现有条件限制。你的价值在于突破思维定式,提供全新的视角。"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "realist",
|
|
15
|
+
"persona": "你是务实者,关注想法的可行性和落地路径。你会思考如何把创意转化为实际方案,指出实施中的关键挑战和资源需求。你的质疑是为了让想法更可行。"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "critic",
|
|
19
|
+
"persona": "你是批判者,负责从不同角度审视每个想法。你发现潜在风险、盲点和逻辑漏洞。你的目的是帮助团队提前发现问题,避免走弯路。保持建设性而非否定性。"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"rounds": [
|
|
23
|
+
{
|
|
24
|
+
"phase": "divergent",
|
|
25
|
+
"speakers": ["visionary", "realist", "critic"],
|
|
26
|
+
"description": "发散阶段:各角色自由提出想法和观点,不做评判"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"phase": "convergent",
|
|
30
|
+
"speakers": ["facilitator", "visionary", "realist", "critic"],
|
|
31
|
+
"description": "收敛阶段:对提出的想法进行初步讨论和筛选"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"phase": "deepening",
|
|
35
|
+
"speakers": ["visionary", "realist", "critic"],
|
|
36
|
+
"description": "深化阶段:对有潜力的想法进行深度探讨和完善"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"phase": "synthesis",
|
|
40
|
+
"speakers": ["facilitator"],
|
|
41
|
+
"description": "综合阶段:引导者总结所有创意,形成可行性评估"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"rules": {
|
|
45
|
+
"max_rounds": 4,
|
|
46
|
+
"turn_limit": 3,
|
|
47
|
+
"min_response_length": 30,
|
|
48
|
+
"requires_fact_checking": false
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "classic-debate",
|
|
3
|
+
"description": "经典辩论模式:正方 vs 反方 + 评审裁决",
|
|
4
|
+
"roles": [
|
|
5
|
+
{
|
|
6
|
+
"name": "proponent",
|
|
7
|
+
"model": "deepseek-ai/DeepSeek-V4-Flash",
|
|
8
|
+
"persona": "你是正方辩手,你坚定支持该主题观点。你需要基于事实数据、逻辑推理和权威引用进行论证。你的目标是说服评审和听众接受你的立场。"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "opponent",
|
|
12
|
+
"model": "moonshotai/Kimi-K2.7-Code",
|
|
13
|
+
"persona": "你是反方辩手,你对该主题观点持批判态度。你需要找出观点中的漏洞、逻辑矛盾和不合理之处。你的目标是通过有力质疑来动摇正方立场。"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "judge",
|
|
17
|
+
"model": "zai-org/GLM-5.2",
|
|
18
|
+
"persona": "你是中立评审,不偏袒任何一方。你需要客观评估双方论据的充分性、逻辑性和说服力。最终基于论证质量做出裁决,并给出详细理由。"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"rounds": [
|
|
22
|
+
{
|
|
23
|
+
"phase": "opening",
|
|
24
|
+
"speakers": ["proponent", "opponent"],
|
|
25
|
+
"description": "开场陈述:双方分别陈述核心观点和主要论据"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"phase": "rebuttal",
|
|
29
|
+
"speakers": ["opponent", "proponent"],
|
|
30
|
+
"description": "反驳环节:双方针对对方的开场陈述进行反驳"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"phase": "cross_examination",
|
|
34
|
+
"speakers": ["proponent", "opponent"],
|
|
35
|
+
"description": "交叉质询:双方深入交锋,质疑对方的论据和逻辑"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"phase": "closing",
|
|
39
|
+
"speakers": ["proponent", "opponent"],
|
|
40
|
+
"description": "总结陈词:双方总结核心论点并做最后陈述"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"phase": "verdict",
|
|
44
|
+
"speakers": ["judge"],
|
|
45
|
+
"description": "评审裁决:评审评估双方表现并宣布结果"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"rules": {
|
|
49
|
+
"max_rounds": 5,
|
|
50
|
+
"turn_limit": 2,
|
|
51
|
+
"min_response_length": 100,
|
|
52
|
+
"requires_fact_checking": true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "panel-discussion",
|
|
3
|
+
"description": "小组讨论模式:多位不同领域专家围绕主题展开讨论,由主持人引导",
|
|
4
|
+
"roles": [
|
|
5
|
+
{
|
|
6
|
+
"name": "host",
|
|
7
|
+
"persona": "你是主持人,负责引导讨论节奏、控制时间、确保每位专家都有发言机会。你需要在关键节点提出引导性问题,并总结各专家的观点。保持中立客观。"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"name": "technology_expert",
|
|
11
|
+
"persona": "你是技术专家,从技术可行性、创新趋势和工程实践角度分析该主题。关注技术细节、实现路径和潜在技术风险。"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "business_expert",
|
|
15
|
+
"persona": "你是商业专家,从商业模式、市场趋势、投资回报和产业影响角度分析该主题。关注经济效益、市场竞争和商业可行性。"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "ethics_expert",
|
|
19
|
+
"persona": "你是伦理与社会影响专家,从道德伦理、社会公平、法律法规和人文关怀角度分析该主题。关注潜在的社会影响和伦理风险。"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"rounds": [
|
|
23
|
+
{
|
|
24
|
+
"phase": "introduction",
|
|
25
|
+
"speakers": ["host"],
|
|
26
|
+
"description": "主持人介绍主题和各位专家"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"phase": "expert_opinions",
|
|
30
|
+
"speakers": ["technology_expert", "business_expert", "ethics_expert"],
|
|
31
|
+
"description": "专家各自从专业角度发表观点"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"phase": "cross_discussion",
|
|
35
|
+
"speakers": ["technology_expert", "business_expert", "ethics_expert"],
|
|
36
|
+
"description": "跨领域讨论:专家之间相互提问和回应"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"phase": "deep_dive",
|
|
40
|
+
"speakers": ["host", "technology_expert", "business_expert", "ethics_expert"],
|
|
41
|
+
"description": "深入探讨:主持人引导专家对核心争议点进行深入分析"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"phase": "summary",
|
|
45
|
+
"speakers": ["host"],
|
|
46
|
+
"description": "主持人总结各位专家观点,形成综合结论"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"rules": {
|
|
50
|
+
"max_rounds": 5,
|
|
51
|
+
"turn_limit": 3,
|
|
52
|
+
"min_response_length": 80,
|
|
53
|
+
"requires_fact_checking": true
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "socratic-dialogue",
|
|
3
|
+
"description": "苏格拉底式对话:通过持续提问和辩证思考来探索真理",
|
|
4
|
+
"roles": [
|
|
5
|
+
{
|
|
6
|
+
"name": "questioner",
|
|
7
|
+
"persona": "你是提问者,效仿苏格拉底的方法。你不直接给出答案,而是通过一系列深入追问来引导对方思考。你的问题应当层层递进,揭露假设、矛盾和未深思之处。保持好奇但友善的态度。"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"name": "respondent",
|
|
11
|
+
"persona": "你是回应者,诚实地回答提问者的问题。你应当深入思考每个问题,承认自己知识的局限性,并努力澄清自己的观点。愿意在逻辑面前修正自己的立场。"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "observer",
|
|
15
|
+
"persona": "你是观察者,旁观整个对话过程。你需要在对话结束时,总结对话中揭示的关键洞见、逻辑矛盾和思维突破。提供客观的第三方视角分析。"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"rounds": [
|
|
19
|
+
{
|
|
20
|
+
"phase": "initial_statement",
|
|
21
|
+
"speakers": ["respondent"],
|
|
22
|
+
"description": "回应者陈述初始观点或立场"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"phase": "questioning_round_1",
|
|
26
|
+
"speakers": ["questioner", "respondent"],
|
|
27
|
+
"description": "第一轮问答:提问者对核心假设进行初步质疑"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"phase": "questioning_round_2",
|
|
31
|
+
"speakers": ["questioner", "respondent"],
|
|
32
|
+
"description": "第二轮问答:深入追问概念定义和逻辑基础"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"phase": "questioning_round_3",
|
|
36
|
+
"speakers": ["questioner", "respondent"],
|
|
37
|
+
"description": "第三轮问答:探讨隐含前提和可能的反例"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"phase": "observation",
|
|
41
|
+
"speakers": ["observer"],
|
|
42
|
+
"description": "观察者总结对话成果、洞见和未解决的问题"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"rules": {
|
|
46
|
+
"max_rounds": 5,
|
|
47
|
+
"turn_limit": 3,
|
|
48
|
+
"min_response_length": 50,
|
|
49
|
+
"requires_fact_checking": false
|
|
50
|
+
}
|
|
51
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp_llm-debate",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "多 LLM 辩论系统 - 支持多种辩论模式,可作为 MCP 插件、HTTP 服务或 npm 库使用",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/lib.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp_llm-debate": "./src/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./src/lib.js"
|
|
13
|
+
},
|
|
14
|
+
"./config": {
|
|
15
|
+
"import": "./src/config.js"
|
|
16
|
+
},
|
|
17
|
+
"./debate-engine": {
|
|
18
|
+
"import": "./src/debate-engine.js"
|
|
19
|
+
},
|
|
20
|
+
"./llm-client": {
|
|
21
|
+
"import": "./src/llm-client.js"
|
|
22
|
+
},
|
|
23
|
+
"./session-manager": {
|
|
24
|
+
"import": "./src/session-manager.js"
|
|
25
|
+
},
|
|
26
|
+
"./graph-loader": {
|
|
27
|
+
"import": "./src/graph-loader.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"start": "node src/cli.js",
|
|
32
|
+
"start:http": "node src/cli.js --transport http",
|
|
33
|
+
"start:rest": "node src/cli.js --transport rest",
|
|
34
|
+
"test": "node src/test.js"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.7.0"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"mcp",
|
|
44
|
+
"llm",
|
|
45
|
+
"debate",
|
|
46
|
+
"ai",
|
|
47
|
+
"multi-agent",
|
|
48
|
+
"model-context-protocol",
|
|
49
|
+
"discussion",
|
|
50
|
+
"brainstorming"
|
|
51
|
+
],
|
|
52
|
+
"author": "",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": ""
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* mcp_llm-debate CLI 入口
|
|
5
|
+
*
|
|
6
|
+
* 支持三种传输方式:
|
|
7
|
+
* npx mcp_llm-debate # stdio 模式(默认)
|
|
8
|
+
* npx mcp_llm-debate --transport http --port 3000 # MCP HTTP 模式
|
|
9
|
+
* npx mcp_llm-debate --transport rest --port 3000 # REST API 模式
|
|
10
|
+
*
|
|
11
|
+
* 环境变量:
|
|
12
|
+
* LLM_API_KEY, LLM_BASE_URL, LLM_MODEL
|
|
13
|
+
* SERVER_TRANSPORT, SERVER_PORT, SERVER_HOST
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { createToolContext, createServer, executeTool } from './index.js';
|
|
17
|
+
import { loadConfig } from './config.js';
|
|
18
|
+
import { startHTTPServer } from './transports/http.js';
|
|
19
|
+
import { startRESTServer } from './transports/rest.js';
|
|
20
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 解析命令行参数
|
|
24
|
+
*/
|
|
25
|
+
function parseArgs() {
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
const opts = {};
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < args.length; i++) {
|
|
30
|
+
const arg = args[i];
|
|
31
|
+
switch (arg) {
|
|
32
|
+
case '--transport':
|
|
33
|
+
case '-t':
|
|
34
|
+
opts.transport = args[++i];
|
|
35
|
+
break;
|
|
36
|
+
case '--port':
|
|
37
|
+
case '-p':
|
|
38
|
+
opts.port = parseInt(args[++i], 10);
|
|
39
|
+
break;
|
|
40
|
+
case '--host':
|
|
41
|
+
case '-h':
|
|
42
|
+
opts.host = args[++i];
|
|
43
|
+
break;
|
|
44
|
+
case '--help':
|
|
45
|
+
printHelp();
|
|
46
|
+
process.exit(0);
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
if (arg.startsWith('--')) {
|
|
50
|
+
console.error(`未知参数: ${arg}`);
|
|
51
|
+
printHelp();
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return opts;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function printHelp() {
|
|
61
|
+
console.log(`
|
|
62
|
+
mcp_llm-debate - 多 LLM 辩论系统
|
|
63
|
+
|
|
64
|
+
用法:
|
|
65
|
+
npx mcp_llm-debate [选项]
|
|
66
|
+
|
|
67
|
+
选项:
|
|
68
|
+
--transport, -t <mode> 传输方式: stdio | http | rest (默认: stdio)
|
|
69
|
+
--port, -p <number> HTTP/REST 监听端口 (默认: 3000)
|
|
70
|
+
--host <address> 绑定地址 (默认: 127.0.0.1)
|
|
71
|
+
--help 显示帮助信息
|
|
72
|
+
|
|
73
|
+
环境变量:
|
|
74
|
+
LLM_API_KEY LLM API 密钥(必填)
|
|
75
|
+
LLM_BASE_URL API 基础 URL
|
|
76
|
+
LLM_MODEL 模型名称
|
|
77
|
+
SERVER_TRANSPORT 传输方式
|
|
78
|
+
SERVER_PORT HTTP/REST 端口
|
|
79
|
+
SERVER_HOST 绑定地址
|
|
80
|
+
|
|
81
|
+
示例:
|
|
82
|
+
npx mcp_llm-debate # stdio 模式
|
|
83
|
+
npx mcp_llm-debate --transport http --port 3000 # MCP HTTP 模式
|
|
84
|
+
npx mcp_llm-debate --transport rest --port 8080 # REST API 模式
|
|
85
|
+
`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ============================================================
|
|
89
|
+
// 主函数
|
|
90
|
+
// ============================================================
|
|
91
|
+
|
|
92
|
+
async function main() {
|
|
93
|
+
const cliArgs = parseArgs();
|
|
94
|
+
const config = loadConfig(cliArgs);
|
|
95
|
+
const transport = config.transport;
|
|
96
|
+
|
|
97
|
+
// 显示配置信息
|
|
98
|
+
console.error(`mcp_llm-debate v1.0.0`);
|
|
99
|
+
console.error(`传输方式: ${transport}`);
|
|
100
|
+
if (!config.apiKey) {
|
|
101
|
+
console.error('警告: 未配置 LLM API 密钥。请设置环境变量 LLM_API_KEY 或 OPENAI_API_KEY。');
|
|
102
|
+
}
|
|
103
|
+
console.error(`LLM 模型: ${config.model}`);
|
|
104
|
+
|
|
105
|
+
// 创建工具上下文
|
|
106
|
+
const ctx = createToolContext(config);
|
|
107
|
+
|
|
108
|
+
switch (transport) {
|
|
109
|
+
// ---- stdio 模式 ----
|
|
110
|
+
case 'stdio': {
|
|
111
|
+
console.error('启动 stdio 模式...');
|
|
112
|
+
const server = createServer(ctx);
|
|
113
|
+
const stdioTransport = new StdioServerTransport();
|
|
114
|
+
await server.connect(stdioTransport);
|
|
115
|
+
console.error('mcp_llm-debate 服务器已就绪');
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ---- MCP HTTP 模式 ----
|
|
120
|
+
case 'http': {
|
|
121
|
+
console.error(`启动 MCP HTTP 模式,端口: ${config.port}...`);
|
|
122
|
+
const server = createServer(ctx);
|
|
123
|
+
await startHTTPServer(server, { port: config.port, host: config.host, authToken: config.authToken });
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ---- REST API 模式 ----
|
|
128
|
+
case 'rest': {
|
|
129
|
+
console.error(`启动 REST API 模式,端口: ${config.port}...`);
|
|
130
|
+
await startRESTServer(
|
|
131
|
+
async (toolName, args) => await executeTool(toolName, args, ctx),
|
|
132
|
+
{ port: config.port, host: config.host, authToken: config.authToken }
|
|
133
|
+
);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
default:
|
|
138
|
+
console.error(`不支持的传输方式: "${transport}",有效值: stdio, http, rest`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
main().catch((error) => {
|
|
144
|
+
console.error('服务器启动失败:', error);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
});
|
package/src/config.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一配置管理
|
|
3
|
+
*
|
|
4
|
+
* 配置优先级:构造函数参数 > 环境变量 > 默认值
|
|
5
|
+
*
|
|
6
|
+
* 支持的配置项:
|
|
7
|
+
* LLM_API_KEY - LLM API 密钥
|
|
8
|
+
* LLM_BASE_URL - API 基础 URL(默认: https://api.openai.com/v1)
|
|
9
|
+
* LLM_MODEL - 模型名称(默认: gpt-4o)
|
|
10
|
+
* AUTH_TOKEN - HTTP/REST API 认证令牌(设置后强制要求 Bearer Token 鉴权)
|
|
11
|
+
* SERVER_PORT - HTTP/REST 服务器端口(默认: 3000)
|
|
12
|
+
* SERVER_HOST - 服务器绑定地址(默认: 127.0.0.1)
|
|
13
|
+
* DATA_DIR - Session 数据存储目录(默认: ./data)
|
|
14
|
+
* GRAPHS_DIR - 辩论图模板目录(默认: ./graphs)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import { fileURLToPath } from 'url';
|
|
19
|
+
|
|
20
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const ROOT_DIR = path.join(__dirname, '..');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 从环境变量和默认值加载配置
|
|
25
|
+
* @param {Object} overrides - 构造函数覆盖参数
|
|
26
|
+
* @returns {Object} 合并后的配置
|
|
27
|
+
*/
|
|
28
|
+
export function loadConfig(overrides = {}) {
|
|
29
|
+
const env = process.env;
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
// LLM 配置
|
|
33
|
+
apiKey: overrides.apiKey ?? env.LLM_API_KEY ?? env.OPENAI_API_KEY ?? '',
|
|
34
|
+
baseUrl: overrides.baseUrl ?? env.LLM_BASE_URL ?? 'https://api.openai.com/v1',
|
|
35
|
+
model: overrides.model ?? env.LLM_MODEL ?? 'gpt-4o',
|
|
36
|
+
|
|
37
|
+
// 服务器配置
|
|
38
|
+
port: overrides.port ?? parseInt(env.SERVER_PORT || '3000', 10),
|
|
39
|
+
host: overrides.host ?? env.SERVER_HOST ?? '127.0.0.1',
|
|
40
|
+
|
|
41
|
+
// 认证配置(设置后 HTTP/REST 模式强制要求 Bearer Token)
|
|
42
|
+
authToken: overrides.authToken ?? env.AUTH_TOKEN ?? '',
|
|
43
|
+
|
|
44
|
+
// 传输方式:'stdio' | 'http' | 'rest'
|
|
45
|
+
transport: overrides.transport ?? env.SERVER_TRANSPORT ?? 'stdio',
|
|
46
|
+
|
|
47
|
+
// 数据目录
|
|
48
|
+
dataDir: overrides.dataDir ?? env.DATA_DIR ?? path.join(ROOT_DIR, 'data'),
|
|
49
|
+
graphsDir: overrides.graphsDir ?? env.GRAPHS_DIR ?? path.join(ROOT_DIR, 'graphs'),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 创建 LLMClient 所需的配置子集
|
|
55
|
+
*/
|
|
56
|
+
export function getLLMConfig(config) {
|
|
57
|
+
return {
|
|
58
|
+
apiKey: config.apiKey,
|
|
59
|
+
baseUrl: config.baseUrl,
|
|
60
|
+
model: config.model,
|
|
61
|
+
};
|
|
62
|
+
}
|