Compare commits

...

3 Commits

Author SHA1 Message Date
claude-code-best
6585d0f67c fix: 禁用 COORDINATOR_MODE 和 TEAMMEM 解决内存溢出问题
COORDINATOR_MODE 的 AgentSummary 每 30s fork 完整消息历史是 GB 级内存泄露的主因,
TEAMMEM 依赖 COORDINATOR_MODE 且邮箱文件无限增长。同时恢复 DAEMON(非主因)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 20:29:52 +08:00
claude-code-best
e4403ff010 fix: 移除 RCS 按 machineName 复用 agent 记录的逻辑
多个同名 acp-link 实例注册到 RCS 时,REST 注册阶段按 machineName
去重导致不同实例共享同一条记录。改为每次注册都创建独立记录,
重连恢复由 WS identify 阶段按 environment_id 精确匹配。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 19:27:58 +08:00
claude-code-best
9e61e7a90d chore: 更新 biome 注释 2026-04-25 16:33:02 +08:00
3 changed files with 10 additions and 68 deletions

View File

@@ -98,22 +98,6 @@ export function storeDeleteToken(token: string): boolean {
// ---------- Environment ----------
/** Find an active or offline environment by machineName (optionally filtered by workerType).
* Includes "offline" so ACP agents can be reused on reconnect. */
export function storeFindEnvironmentByMachineName(
machineName: string,
workerType?: string,
): EnvironmentRecord | undefined {
for (const rec of environments.values()) {
if (rec.machineName === machineName && (rec.status === "active" || rec.status === "offline")) {
if (!workerType || rec.workerType === workerType) {
return rec;
}
}
}
return undefined;
}
export function storeCreateEnvironment(req: {
secret: string;
machineName?: string;
@@ -126,23 +110,6 @@ export function storeCreateEnvironment(req: {
username?: string;
capabilities?: Record<string, unknown>;
}): EnvironmentRecord {
// ACP: reuse existing active record by machineName
if (req.workerType === "acp" && req.machineName) {
const existing = storeFindEnvironmentByMachineName(req.machineName, "acp");
if (existing) {
Object.assign(existing, {
status: "active",
lastPollAt: new Date(),
updatedAt: new Date(),
maxSessions: req.maxSessions ?? existing.maxSessions,
bridgeId: req.bridgeId ?? existing.bridgeId,
capabilities: req.capabilities ?? existing.capabilities,
username: req.username ?? existing.username,
});
return existing;
}
}
const id = `env_${uuid().replace(/-/g, "")}`;
const now = new Date();
const record: EnvironmentRecord = {

View File

@@ -30,33 +30,33 @@ export const DEFAULT_BUILD_FEATURES = [
'BUDDY', // 陪伴宠物角色Squirtle Waddles
'TRANSCRIPT_CLASSIFIER', // 对话分类器,用于标注会话类型
'BRIDGE_MODE', // Remote Control / Bridge 模式,远程控制会话
'AGENT_TRIGGERS_REMOTE', // Agent 触发远程会话连接
'AGENT_TRIGGERS_REMOTE', // sessionIngress 模块级 Map 累积(非 GB 级主因)
'CHICAGO_MCP', // Chicago MCP 集成(内部代号)
'VOICE_MODE', // Push-to-Talk 语音输入模式
'SHOT_STATS', // 单次请求统计信息收集
'PROMPT_CACHE_BREAK_DETECTION', // 检测 prompt cache 是否被打破
'PROMPT_CACHE_BREAK_DETECTION', // 检测 prompt cache 是否被打破(有 10 条上限,可控)
'TOKEN_BUDGET', // Token 预算管理与控制
// P0: local features
'AGENT_TRIGGERS', // 本地 Agent 触发器(工具调用时启动子代理)
'ULTRATHINK', // 超深度思考模式,增加推理链长度
'BUILTIN_EXPLORE_PLAN_AGENTS', // 内置 Explore/Plan 子代理类型
'LODESTONE', // 上下文锚点,优化长对话的相关性检索
'EXTRACT_MEMORIES', // 自动从对话中提取并持久化记忆
'VERIFICATION_AGENT', // 验证代理,任务完成后自动校验结果
'EXTRACT_MEMORIES', // 每次 turn 结束 fork 完整消息历史(非 GB 级主因)
'VERIFICATION_AGENT', // 任务完成后 fork 完整消息(非 GB 级主因)
'KAIROS_BRIEF', // Kairos 定时摘要(定时汇报当前状态)
'AWAY_SUMMARY', // 离线摘要(用户离开后生成总结)
'ULTRAPLAN', // 超级规划模式,深度分析后生成实施计划
// 'DAEMON', // 守护进程模式,长驻 supervisor 管理后台 worker已禁用:内存占用过高
'DAEMON', // 守护进程模式,长驻 supervisor 管理后台 worker非 GB 级主因
'ACP', // ACP 代理协议,支持外部 agent 接入
'WORKFLOW_SCRIPTS', // 工作流脚本(.claude/workflows/ 中的 YAML/MD
'HISTORY_SNIP', // 历史消息裁剪,压缩上下文窗口
'CONTEXT_COLLAPSE', // 上下文折叠,自动压缩旧消息
'MONITOR_TOOL', // Monitor 工具,流式监控后台进程输出
'FORK_SUBAGENT', // Fork 子代理,在隔离上下文中并行执行任务
'UDS_INBOX', // Unix Domain Socket 收件箱,跨会话消息传递
'UDS_INBOX', // inbox 数组只增不减(非 GB 级主因)
'KAIROS', // Kairos 定时任务系统核心
'COORDINATOR_MODE', // 协调者模式,多代理团队任务调度
'LAN_PIPES', // 局域网管道LAN 设备间通信
// 'COORDINATOR_MODE', // 已禁用AgentSummary 30s fork 循环GB 级泄露主因
'LAN_PIPES', // 依赖 UDS_INBOX已随 UDS_INBOX 恢复)
'BG_SESSIONS', // 后台会话管理ps/logs/attach/kill
'TEMPLATES', // 模板任务new/list/reply 子命令)
// 'REVIEW_ARTIFACT', // 代码审查产物API 请求无响应,待排查 schema 兼容性)
@@ -68,11 +68,11 @@ export const DEFAULT_BUILD_FEATURES = [
'DIRECT_CONNECT', // 直连模式claude server / claude open
// Skill search & learning
'EXPERIMENTAL_SKILL_SEARCH', // 实验性技能搜索DiscoverSkills
'SKILL_LEARNING', // 技能学习系统,从对话中自动生成/演化技能
'SKILL_LEARNING', // projectContext cache 无淘汰机制(非 GB 级主因)
// P3: poor mode
'POOR', // 穷鬼模式,跳过 extract_memories/prompt_suggestion 减少消耗
// Team Memory
'TEAMMEM', // 团队记忆,代理队友间共享记忆文件
// 'TEAMMEM', // 已禁用:依赖 COORDINATOR_MODE邮箱文件无限增长
// SSH Remote
'SSH_REMOTE', // SSH 远程连接,本地 REPL + 远端工具执行
]as const;

View File

@@ -190,12 +190,10 @@ export async function mcpListHandler(): Promise<void> {
logEvent('tengu_mcp_list', {})
const { servers: configs } = await getAllMcpConfigs()
if (Object.keys(configs).length === 0) {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(
'No MCP servers configured. Use `claude mcp add` to add a server.',
)
} else {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log('Checking MCP server health...\n')
// Check servers concurrently
@@ -213,18 +211,14 @@ export async function mcpListHandler(): Promise<void> {
for (const { name, server, status } of results) {
// Intentionally excluding sse-ide servers here since they're internal
if (server.type === 'sse') {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(`${name}: ${server.url} (SSE) - ${status}`)
} else if (server.type === 'http') {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(`${name}: ${server.url} (HTTP) - ${status}`)
} else if (server.type === 'claudeai-proxy') {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(`${name}: ${server.url} - ${status}`)
} else if (!server.type || server.type === 'stdio') {
const stdioServer = server as { command: string; args: string[]; type?: string }
const args = Array.isArray(stdioServer.args) ? stdioServer.args : []
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(`${name}: ${stdioServer.command} ${args.join(' ')} - ${status}`)
}
}
@@ -244,27 +238,20 @@ export async function mcpGetHandler(name: string): Promise<void> {
cliError(`No MCP server found with name: ${name}`)
}
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(`${name}:`)
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` Scope: ${getScopeLabel(server.scope)}`)
// Check server health
const status = await checkMcpServerHealth(name, server)
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` Status: ${status}`)
// Intentionally excluding sse-ide servers here since they're internal
if (server.type === 'sse') {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` Type: sse`)
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` URL: ${server.url}`)
if (server.headers) {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(' Headers:')
for (const [key, value] of Object.entries(server.headers)) {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` ${key}: ${value}`)
}
}
@@ -277,19 +264,14 @@ export async function mcpGetHandler(name: string): Promise<void> {
}
if (server.oauth.callbackPort)
parts.push(`callback_port ${server.oauth.callbackPort}`)
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` OAuth: ${parts.join(', ')}`)
}
} else if (server.type === 'http') {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` Type: http`)
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` URL: ${server.url}`)
if (server.headers) {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(' Headers:')
for (const [key, value] of Object.entries(server.headers)) {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` ${key}: ${value}`)
}
}
@@ -302,27 +284,20 @@ export async function mcpGetHandler(name: string): Promise<void> {
}
if (server.oauth.callbackPort)
parts.push(`callback_port ${server.oauth.callbackPort}`)
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` OAuth: ${parts.join(', ')}`)
}
} else if (server.type === 'stdio') {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` Type: stdio`)
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` Command: ${server.command}`)
const args = Array.isArray(server.args) ? server.args : []
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` Args: ${args.join(' ')}`)
if (server.env) {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(' Environment:')
for (const [key, value] of Object.entries(server.env)) {
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(` ${key}=${value}`)
}
}
}
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(
`\nTo remove this server, run: claude mcp remove "${name}" -s ${server.scope}`,
)