team-anya 0.2.5 → 0.2.7

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.
@@ -243,6 +243,13 @@ export class CCBroker extends EventEmitter {
243
243
  get instanceCount() {
244
244
  return this.instances.size;
245
245
  }
246
+ maxInstances(role) {
247
+ if (role === 'loid')
248
+ return this.maxLoidInstances;
249
+ if (role === 'yor')
250
+ return this.maxYorInstances;
251
+ return this.maxFrankyInstances;
252
+ }
246
253
  // ── 私有 ──
247
254
  shutdownResolve = null;
248
255
  countByRole(role) {
@@ -32,7 +32,9 @@ const envSchema = z.object({
32
32
  SQLITE_PATH: z.string().optional(),
33
33
  ANYA_HOME: z.string().default(defaultAnyaHome).transform(resolveHome),
34
34
  WORKSPACE_PATH: z.string().optional(),
35
- MAX_YOR_CONCURRENCY: z.coerce.number().min(1).max(10).default(3),
35
+ MAX_LOID_CONCURRENCY: z.coerce.number().min(1).default(100),
36
+ MAX_YOR_CONCURRENCY: z.coerce.number().min(1).default(100),
37
+ MAX_FRANKY_CONCURRENCY: z.coerce.number().min(1).default(100),
36
38
  CLAUDE_CODE_BINARY: z.string().default('claude'),
37
39
  LOID_WORK_DIR: z.string().optional(),
38
40
  LOID_PROTOCOLS_DIR: z.string().default(resolve(PKG_ROOT, 'blueprint/protocols')),
@@ -43,8 +43,6 @@ function createFrankyMcpServer(deps) {
43
43
  *
44
44
  * 所有工具实现来自 @team-anya/mcp-tools。
45
45
  */
46
- /** Franky MCP server 固定端口 */
47
- export const FRANKY_MCP_PORT = 19530;
48
46
  export async function startFrankyMcpServer(deps) {
49
47
  const sessions = new Map();
50
48
  const httpServer = createServer(async (req, res) => {
@@ -80,8 +78,10 @@ export async function startFrankyMcpServer(deps) {
80
78
  sessions.set(transport.sessionId, { server, transport });
81
79
  }
82
80
  });
83
- await new Promise((resolve) => {
84
- httpServer.listen(FRANKY_MCP_PORT, '127.0.0.1', resolve);
81
+ // 使用动态端口(port 0),避免多个 Franky 实例抢占同一端口导致 EADDRINUSE 崩溃
82
+ await new Promise((resolve, reject) => {
83
+ httpServer.on('error', reject);
84
+ httpServer.listen(0, '127.0.0.1', resolve);
85
85
  });
86
86
  const addr = httpServer.address();
87
87
  const port = typeof addr === 'object' && addr !== null ? addr.port : 0;
@@ -150,6 +150,21 @@ export async function registerRoutes(app, deps) {
150
150
  const todayEventsCount = todayEventsResult?.count ?? 0;
151
151
  // 未处理机会
152
152
  const recentOpportunities = getOpenOpportunities(db);
153
+ // 各角色活跃 session 统计
154
+ const activeInstances = {
155
+ loid: {
156
+ active: slotStatus.filter(s => s.role === 'loid' && s.state !== 'disposed').length,
157
+ max: broker.maxInstances('loid'),
158
+ },
159
+ yor: {
160
+ active: slotStatus.filter(s => s.role === 'yor' && s.state !== 'disposed').length,
161
+ max: broker.maxInstances('yor'),
162
+ },
163
+ franky: {
164
+ active: slotStatus.filter(s => s.role === 'franky' && s.state !== 'disposed').length,
165
+ max: broker.maxInstances('franky'),
166
+ },
167
+ };
153
168
  return reply.send({
154
169
  statusCounts,
155
170
  totalTasks: allTasks.length,
@@ -159,6 +174,7 @@ export async function registerRoutes(app, deps) {
159
174
  busy: slotStatus.filter(s => s.role === 'yor' && s.state === 'executing').length,
160
175
  available: 0,
161
176
  },
177
+ activeInstances,
162
178
  recentTasks: allTasks.slice(-10).reverse(),
163
179
  // C3 新增字段
164
180
  overdueCommitments,
@@ -43,8 +43,6 @@ function createMcpServer(deps) {
43
43
  * 所有工具实现来自 @team-anya/mcp-tools,
44
44
  * 这里只负责 HTTP 传输和 session 管理。
45
45
  */
46
- /** Loid MCP server 固定端口 */
47
- export const LOID_MCP_PORT = 19510;
48
46
  export async function startLoidMcpServer(deps) {
49
47
  const sessions = new Map();
50
48
  const httpServer = createServer(async (req, res) => {
@@ -89,8 +87,10 @@ export async function startLoidMcpServer(deps) {
89
87
  sessions.set(transport.sessionId, { server, transport });
90
88
  }
91
89
  });
92
- await new Promise((resolve) => {
93
- httpServer.listen(LOID_MCP_PORT, '127.0.0.1', resolve);
90
+ // 使用动态端口(port 0),避免重启时旧端口未释放导致 EADDRINUSE
91
+ await new Promise((resolve, reject) => {
92
+ httpServer.on('error', reject);
93
+ httpServer.listen(0, '127.0.0.1', resolve);
94
94
  });
95
95
  const addr = httpServer.address();
96
96
  const port = typeof addr === 'object' && addr !== null ? addr.port : 0;
@@ -167,9 +167,9 @@ export async function buildServer() {
167
167
  });
168
168
  // CCBroker — 统一 CC 进程管理器
169
169
  const broker = new CCBroker({
170
- maxLoidInstances: 2,
170
+ maxLoidInstances: config.MAX_LOID_CONCURRENCY,
171
171
  maxYorInstances: config.MAX_YOR_CONCURRENCY,
172
- maxFrankyInstances: 2,
172
+ maxFrankyInstances: config.MAX_FRANKY_CONCURRENCY,
173
173
  logger: app.log,
174
174
  });
175
175
  // YorOrchestrator — 替代 Yor 子进程,通过 CCBroker 管理 Yor CC
@@ -39,8 +39,6 @@ function createYorMcpServer(deps) {
39
39
  *
40
40
  * 所有工具实现来自 @team-anya/mcp-tools。
41
41
  */
42
- /** Yor MCP server 固定端口 */
43
- export const YOR_MCP_PORT = 19520;
44
42
  export async function startYorMcpServer(deps) {
45
43
  const sessions = new Map();
46
44
  const httpServer = createServer(async (req, res) => {
@@ -77,8 +75,10 @@ export async function startYorMcpServer(deps) {
77
75
  sessions.set(transport.sessionId, { server, transport });
78
76
  }
79
77
  });
80
- await new Promise((resolve) => {
81
- httpServer.listen(YOR_MCP_PORT, '127.0.0.1', resolve);
78
+ // 使用动态端口(port 0),避免多个 Yor 实例抢占同一端口导致 EADDRINUSE 崩溃
79
+ await new Promise((resolve, reject) => {
80
+ httpServer.on('error', reject);
81
+ httpServer.listen(0, '127.0.0.1', resolve);
82
82
  });
83
83
  const addr = httpServer.address();
84
84
  const port = typeof addr === 'object' && addr !== null ? addr.port : 0;