Compare commits

...

4 Commits

Author SHA1 Message Date
claude-code-best
2a5b263641 chore: 1.9.4 2026-04-24 10:50:53 +08:00
claude-code-best
f2dd5142b3 refactor: 解耦 BRIDGE_MODE 与 DAEMON,禁用 DAEMON 降低内存占用
- 从 DEFAULT_BUILD_FEATURES 注释掉 DAEMON(内存占用过高)
- remoteControlServer 命令门控从 feature('DAEMON') && feature('BRIDGE_MODE')
  改为仅 feature('BRIDGE_MODE'),bridge 不再依赖 daemon
- --daemon-worker 快速路径改为运行时检测,未启用时输出明确错误提示

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 10:01:05 +08:00
claude-code-best
4dcbaf1e66 fix: 修复 ACP 模式下 messageSelector require 失败导致 submitMessage 崩溃
ACP 模式不加载完整的 React/Ink UI 组件,导致 require('src/components/MessageSelector.js')
返回 undefined。添加 try-catch 和 optional chaining fallback。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 09:59:23 +08:00
claude-code-best
0b304730d8 docs: 为 DEFAULT_BUILD_FEATURES 每个 feature flag 添加功能注释
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 09:26:59 +08:00
6 changed files with 66 additions and 51 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "claude-code-best", "name": "claude-code-best",
"version": "1.9.3", "version": "1.9.4",
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal", "description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",
"type": "module", "type": "module",
"author": "claude-code-best <claude-code-best@proton.me>", "author": "claude-code-best <claude-code-best@proton.me>",

View File

@@ -27,51 +27,49 @@ export function getMacroDefines(): Record<string, string> {
* - scripts/dev.ts (bun run dev) * - scripts/dev.ts (bun run dev)
*/ */
export const DEFAULT_BUILD_FEATURES = [ export const DEFAULT_BUILD_FEATURES = [
'BUDDY', 'TRANSCRIPT_CLASSIFIER', 'BRIDGE_MODE', 'BUDDY', // 陪伴宠物角色Squirtle Waddles
'AGENT_TRIGGERS_REMOTE', 'TRANSCRIPT_CLASSIFIER', // 对话分类器,用于标注会话类型
'CHICAGO_MCP', 'BRIDGE_MODE', // Remote Control / Bridge 模式,远程控制会话
'VOICE_MODE', 'AGENT_TRIGGERS_REMOTE', // Agent 触发远程会话连接
'SHOT_STATS', 'CHICAGO_MCP', // Chicago MCP 集成(内部代号)
'PROMPT_CACHE_BREAK_DETECTION', 'VOICE_MODE', // Push-to-Talk 语音输入模式
'TOKEN_BUDGET', 'SHOT_STATS', // 单次请求统计信息收集
'PROMPT_CACHE_BREAK_DETECTION', // 检测 prompt cache 是否被打破
'TOKEN_BUDGET', // Token 预算管理与控制
// P0: local features // P0: local features
'AGENT_TRIGGERS', 'AGENT_TRIGGERS', // 本地 Agent 触发器(工具调用时启动子代理)
'ULTRATHINK', 'ULTRATHINK', // 超深度思考模式,增加推理链长度
'BUILTIN_EXPLORE_PLAN_AGENTS', 'BUILTIN_EXPLORE_PLAN_AGENTS', // 内置 Explore/Plan 子代理类型
'LODESTONE', 'LODESTONE', // 上下文锚点,优化长对话的相关性检索
// P1: API-dependent features 'EXTRACT_MEMORIES', // 自动从对话中提取并持久化记忆
'EXTRACT_MEMORIES', 'VERIFICATION_AGENT', // 验证代理,任务完成后自动校验结果
'VERIFICATION_AGENT', 'KAIROS_BRIEF', // Kairos 定时摘要(定时汇报当前状态)
'KAIROS_BRIEF', 'AWAY_SUMMARY', // 离线摘要(用户离开后生成总结)
'AWAY_SUMMARY', 'ULTRAPLAN', // 超级规划模式,深度分析后生成实施计划
'ULTRAPLAN', // 'DAEMON', // 守护进程模式,长驻 supervisor 管理后台 worker已禁用内存占用过高
// P2: daemon + remote control server 'ACP', // ACP 代理协议,支持外部 agent 接入
'DAEMON', 'WORKFLOW_SCRIPTS', // 工作流脚本(.claude/workflows/ 中的 YAML/MD
// ACP (Agent Client Protocol) agent mode 'HISTORY_SNIP', // 历史消息裁剪,压缩上下文窗口
'ACP', 'CONTEXT_COLLAPSE', // 上下文折叠,自动压缩旧消息
// PR-package restored features 'MONITOR_TOOL', // Monitor 工具,流式监控后台进程输出
'WORKFLOW_SCRIPTS', 'FORK_SUBAGENT', // Fork 子代理,在隔离上下文中并行执行任务
'HISTORY_SNIP', 'UDS_INBOX', // Unix Domain Socket 收件箱,跨会话消息传递
'CONTEXT_COLLAPSE', 'KAIROS', // Kairos 定时任务系统核心
'MONITOR_TOOL', 'COORDINATOR_MODE', // 协调者模式,多代理团队任务调度
'FORK_SUBAGENT', 'LAN_PIPES', // 局域网管道LAN 设备间通信
'UDS_INBOX', 'BG_SESSIONS', // 后台会话管理ps/logs/attach/kill
'KAIROS', 'TEMPLATES', // 模板任务new/list/reply 子命令)
'COORDINATOR_MODE', // 'REVIEW_ARTIFACT', // 代码审查产物API 请求无响应,待排查 schema 兼容性)
'LAN_PIPES',
'BG_SESSIONS',
'TEMPLATES',
// 'REVIEW_ARTIFACT', // API 请求无响应,需进一步排查 schema 兼容性
// API content block types // API content block types
'CONNECTOR_TEXT', 'CONNECTOR_TEXT', // Connector 文本块类型,扩展 API 内容格式
// Attribution tracking // Attribution tracking
'COMMIT_ATTRIBUTION', 'COMMIT_ATTRIBUTION', // Git 提交归属追踪(记录 AI 辅助贡献)
// Server mode (claude server / claude open) // Server mode (claude server / claude open)
'DIRECT_CONNECT', 'DIRECT_CONNECT', // 直连模式claude server / claude open
// Skill search // Skill search
'EXPERIMENTAL_SKILL_SEARCH', 'EXPERIMENTAL_SKILL_SEARCH', // 实验性技能搜索DiscoverSkills
// P3: poor mode (disable extract_memories + prompt_suggestion) // P3: poor mode
'POOR', 'POOR', // 穷鬼模式,跳过 extract_memories/prompt_suggestion 减少消耗
// Team Memory (shared memory files between agent teammates) // Team Memory
'TEAMMEM', 'TEAMMEM', // 团队记忆,代理队友间共享记忆文件
]as const; ]as const;

View File

@@ -86,9 +86,13 @@ import {
// Lazy: MessageSelector.tsx pulls React/ink; only needed for message filtering at query time // Lazy: MessageSelector.tsx pulls React/ink; only needed for message filtering at query time
/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable @typescript-eslint/no-require-imports */
const messageSelector = const messageSelector = (): typeof import('src/components/MessageSelector.js') | null => {
(): typeof import('src/components/MessageSelector.js') => try {
require('src/components/MessageSelector.js') return require('src/components/MessageSelector.js')
} catch {
return null
}
}
import { import {
localCommandOutputToSDKAssistantMessage, localCommandOutputToSDKAssistantMessage,
@@ -466,12 +470,13 @@ export class QueryEngine {
} }
// Filter messages that should be acknowledged after transcript // Filter messages that should be acknowledged after transcript
const _selector = messageSelector()
const replayableMessages = messagesFromUserInput.filter( const replayableMessages = messagesFromUserInput.filter(
msg => msg =>
(msg.type === 'user' && (msg.type === 'user' &&
!msg.isMeta && // Skip synthetic caveat messages !msg.isMeta && // Skip synthetic caveat messages
!msg.toolUseResult && // Skip tool results (they'll be acked from query) !msg.toolUseResult && // Skip tool results (they'll be acked from query)
messageSelector().selectableUserMessagesFilter(msg)) || // Skip non-user-authored messages (task notifications, etc.) (_selector?.selectableUserMessagesFilter(msg) ?? true)) || // Skip non-user-authored messages (task notifications, etc.)
(msg.type === 'system' && msg.subtype === 'compact_boundary'), // Always ack compact boundaries (msg.type === 'system' && msg.subtype === 'compact_boundary'), // Always ack compact boundaries
) )
const messagesToAck = replayUserMessages ? replayableMessages : [] const messagesToAck = replayUserMessages ? replayableMessages : []
@@ -643,8 +648,10 @@ export class QueryEngine {
} }
if (fileHistoryEnabled() && persistSession) { if (fileHistoryEnabled() && persistSession) {
const _sel = messageSelector()
const _filter = _sel?.selectableUserMessagesFilter ?? ((_msg: unknown) => true)
messagesFromUserInput messagesFromUserInput
.filter(messageSelector().selectableUserMessagesFilter) .filter(_filter)
.forEach(message => { .forEach(message => {
void fileHistoryMakeSnapshot( void fileHistoryMakeSnapshot(
(updater: (prev: FileHistoryState) => FileHistoryState) => { (updater: (prev: FileHistoryState) => FileHistoryState) => {

View File

@@ -75,7 +75,7 @@ const bridge = feature('BRIDGE_MODE')
? require('./commands/bridge/index.js').default ? require('./commands/bridge/index.js').default
: null : null
const remoteControlServerCommand = const remoteControlServerCommand =
feature('DAEMON') && feature('BRIDGE_MODE') feature('BRIDGE_MODE')
? require('./commands/remoteControlServer/index.js').default ? require('./commands/remoteControlServer/index.js').default
: null : null
const voiceCommand = feature('VOICE_MODE') const voiceCommand = feature('VOICE_MODE')

View File

@@ -3,9 +3,14 @@ import { isBridgeEnabled } from '../../bridge/bridgeEnabled.js'
import type { Command } from '../../commands.js' import type { Command } from '../../commands.js'
function isEnabled(): boolean { function isEnabled(): boolean {
if (!feature('DAEMON') || !feature('BRIDGE_MODE')) { if (!feature('BRIDGE_MODE')) {
return false return false
} }
if (feature('DAEMON')) {
return isBridgeEnabled()
}
// DAEMON feature disabled — still allow the command but warn at runtime
// that headless/daemon worker mode is unavailable.
return isBridgeEnabled() return isBridgeEnabled()
} }

View File

@@ -170,7 +170,12 @@ async function main(): Promise<void> {
// perf-sensitive. No enableConfigs(), no analytics sinks at this layer — // perf-sensitive. No enableConfigs(), no analytics sinks at this layer —
// workers are lean. If a worker kind needs configs/auth (assistant will), // workers are lean. If a worker kind needs configs/auth (assistant will),
// it calls them inside its run() fn. // it calls them inside its run() fn.
if (feature('DAEMON') && (args[0] === '--daemon-worker' || args[0]?.startsWith('--daemon-worker='))) { if (args[0] === '--daemon-worker' || args[0]?.startsWith('--daemon-worker=')) {
if (!feature('DAEMON')) {
console.error('Error: --daemon-worker requires DAEMON feature to be enabled. Set FEATURE_DAEMON=1 or add DAEMON to DEFAULT_BUILD_FEATURES.')
process.exitCode = 1
return
}
const kind = args[0] === '--daemon-worker' ? args[1] : args[0].split('=')[1] const kind = args[0] === '--daemon-worker' ? args[1] : args[0].split('=')[1]
const { runDaemonWorker } = await import('../daemon/workerRegistry.js') const { runDaemonWorker } = await import('../daemon/workerRegistry.js')
await runDaemonWorker(kind) await runDaemonWorker(kind)