standalone-entry.js
4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* Standalone Entry - 独立运行入口
*
* 三个职责:
* 1. runMasterSession() — Master CLI 会话(默认入口,工具编排)
* 2. runOrchestration() — 完整多 Agent 编排(向后兼容 + 直接执行)
* 3. runSingleAgent() — 单个 Agent 执行(给 Extension mas-run 命令用)
*
* 共享进程级 RunRegistry 单例,确保同一运行时的进程追踪一致。
*/
const path = require('path');
const fs = require('fs');
const { RunRegistry } = require('./engine');
// ─── 进程级单例 ───
let _sharedRegistry = null;
function getRegistry() {
if (!_sharedRegistry) _sharedRegistry = new RunRegistry();
return _sharedRegistry;
}
/**
* 运行完整编排流程
*
* @param {string} task - 任务描述
* @param {object} [options]
* @param {string} [options.workDir] - 工作目录 (默认 cwd)
* @param {number} [options.maxRepairs] - 最大修复轮次 (默认 5)
* @param {string[]} [options.agentFilter] - Agent 过滤列表
* @param {object} [options.config] - 自定义配置 (默认读 agents.json)
* @returns {Promise<object>}
*/
async function runOrchestration(task, options = {}) {
const { Orchestrator } = require('./core/orchestrator');
const config = options.config || loadConfig(options.agentFilter);
const workDir = options.workDir || process.cwd();
const registry = getRegistry();
const orchestrator = new Orchestrator(config, workDir, {
runRegistry: registry,
});
try {
return await orchestrator.execute(task, {
maxIterations: options.maxRepairs || 5,
});
} finally {
await orchestrator.shutdown();
}
}
/**
* 运行单个 Agent
*
* @param {string} agentName - Agent 名称
* @param {string} prompt - 任务 prompt
* @param {object} [options]
* @param {string} [options.workDir] - 工作目录
* @returns {Promise<object>}
*/
async function runSingleAgent(agentName, prompt, options = {}) {
const AgentManager = require('./core/agent-manager');
const config = loadConfig();
const workDir = options.workDir || process.cwd();
const registry = getRegistry();
const manager = new AgentManager(config, workDir, { runRegistry: registry });
try {
return await manager.callAgent(agentName, prompt);
} finally {
await manager.closeAllSessions();
}
}
/**
* 加载配置:从 backends.json 读取 clients/launchers,agents 从可选的 agents.json 补充
* @param {string[]} [agentFilter] - 只保留指定 Agent (master 始终保留)
*/
function loadConfig(agentFilter) {
const configDir = path.resolve(__dirname, '../config');
const backends = JSON.parse(fs.readFileSync(path.join(configDir, 'backends.json'), 'utf-8'));
// 可选:从 config/agents.json 加载静态 agent 定义
let agents = {};
const agentsPath = path.join(configDir, 'agents.json');
if (fs.existsSync(agentsPath)) {
agents = JSON.parse(fs.readFileSync(agentsPath, 'utf-8'));
}
const config = {
...backends,
agents,
agentGroups: {},
settings: { maxIterations: 10, timeout: 600000, logsDir: '.autodev-logs' },
};
// 桥接 launchers → clients
if (config.launchers && !config.clients) {
config.clients = {};
for (const [name, launcher] of Object.entries(config.launchers)) {
config.clients[name] = {
name,
command: launcher.command,
acpArgs: launcher.args || [],
acpProtocol: launcher.protocol || 'acp',
};
}
}
if (agentFilter?.length > 0) {
const filtered = {};
for (const name of agentFilter) {
if (config.agents[name]) filtered[name] = config.agents[name];
}
if (config.agents.master) filtered.master = config.agents.master;
config.agents = filtered;
}
return config;
}
/**
* 运行 Master CLI 会话(默认入口)
*
* 启动一个 MasterSession,Master 可以直接对话或通过工具调用 Sub Agent。
*
* @param {string} message - 用户消息
* @param {object} [options]
* @param {string} [options.workDir] - 工作目录 (默认 cwd)
* @param {object} [options.config] - 自定义配置
* @param {function} [options.onData] - 流式数据回调
* @param {function} [options.onToolCall] - 工具调用通知
* @returns {Promise<object>}
*/
async function runMasterSession(message, options = {}) {
const { MasterSession } = require('./core/master-session');
const config = options.config || loadConfig();
const workDir = options.workDir || process.cwd();
const registry = getRegistry();
const session = new MasterSession(config, workDir, {
runRegistry: registry,
});
try {
return await session.handleMessage(message, {
onData: options.onData,
onToolCall: options.onToolCall,
maxToolRounds: options.maxToolRounds || 10,
});
} finally {
await session.shutdown();
}
}
module.exports = { runMasterSession, runOrchestration, runSingleAgent, getRegistry, loadConfig };