10 Commits

Author SHA1 Message Date
oudecheng
1019dbe8cc refactor(code-quality): 清理 clippy 存量告警(unwrap/clone/redundant 等)
- 移除无用克隆与冗余引用,减少不必要内存分配
- 规范 unwrap/expect 使用,修复可提前失败路径
- 修复 anthropic provider llm_timeout_secs 死代码并补全超时日志
- cargo fmt 统一格式
2026-08-16 23:22:22 +08:00
oudecheng
bf8c227634 refactor: 迁移 parking_lot 锁并优化阻塞 IO 与内存管理
## 锁迁移:std::sync → parking_lot
消除锁中毒(poison)导致的级联崩溃风险。parking_lot 锁不会中毒,
且性能更优。迁移覆盖全部生产代码:
- experts/mod.rs: 4 RwLock + 13 expect
- skills/mod.rs: 1 RwLock + 11 expect
- tools/registry.rs: 1 RwLock + 2 expect
- gateway/model_selection.rs: 1 RwLock + 2 expect
- tools/task/repository.rs: 1 RwLock + 4 unwrap
- tools/task/runtime.rs: 2 RwLock + 17 expect
- gateway/session.rs + task/runtime.rs: stream_message_id Mutex
- gateway/processor.rs: description_generation_in_flight Mutex
- command/handler.rs + help.rs: metadata Mutex(公开 API)
- mcp/client.rs: stderr_lines Mutex

测试代码中的 std::sync::Mutex(串行化锁 + TestObserver)有意保留,
已通过 unwrap_or_else(|err| err.into_inner()) 做中毒恢复。

## P1: 阻塞 IO 迁移到 spawn_blocking
将 3 处阻塞 async worker 的操作迁移到 blocking 线程池:
- file_read.rs: read_to_string + 行处理 + base64 编码整体包入 spawn_blocking
- agent_loop.rs: 新增 preencode_images_for_request 两阶段预编码
  (顺序分配预算 → 并行 spawn_blocking 编码),build_llm_request 改为 async
- wechat.rs: media_to_send_content 改为 async,std::fs::read 用 spawn_blocking 包裹

## P2: session_history topic_histories 内存上限
新增 MAX_CACHED_TOPICS=32 上限和 evict_inactive_if_needed 方法。
超限时驱逐非活跃 topic(不在 chat_topic_ids、不在 compression_in_flight、
serial_lock 未被持有)。活跃 topic 永不误驱逐。
remove_history 同步清理 topic_serial_locks,防止无限增长。

## P3: 减少 panic 面
agent_loop.rs retry 循环的 response.expect(...) 改为 ok_or_else(...)?
返回 AgentError::Other,逻辑 bug 不再导致整个 agent 崩溃。

## 对抗性审查修复
- preencode_images_for_request: 用 seen HashSet 去重,防止同 path 重复
  编码导致 HashMap entry 覆盖(NoBudget 覆盖 Encoded 等)
- evict_inactive_if_needed: 检查 topic_serial_lock.try_lock(),防止驱逐
  正在 agent 处理中的 topic(original_topic_id 不在 chat_topic_ids 但
  agent 仍持锁)
- remove_history: 清理 topic_serial_locks

## 验证
- cargo check: 通过(仅既有 lifetime 警告)
- cargo test: 559 passed / 3 failed(均为环境/sandbox 权限问题,与本次改动无关)
2026-08-06 08:18:04 +08:00
oudecheng
cda14360af chore: 建立工程化基线(rustfmt + clippy + CI + eslint + prettier)
配置:
- rustfmt.toml: 固化 max_width=100 / 4 空格缩进,cargo fmt 全量格式化
- Cargo.toml: 配置 [lints.rust] 与 [lints.clippy] 渐进式规则
- .github/workflows/ci.yml: Rust(fmt+clippy+test) + 前端(eslint+tsc+test) 双平台 CI
- Makefile: 新增 check/fmt/fix 目标,clippy 对齐 --all-targets --all-features
- web: eslint flat config + prettier 配置 + package.json 脚本与依赖
- src/main.rs: loop→while 修复 clippy::never_loop

对抗性审查发现并修复:
- eslint 缺 caughtErrorsIgnorePattern 导致 catch(_) 误报为 error
- 前端 lint 未接入 CI,现已补上 Lint 步骤
- Makefile 与 CI 的 clippy flags 不一致,已对齐
2026-08-03 23:24:02 +08:00
oudecheng
dc9211548a feat(model): 专家和子代理支持独立配置 provider/model
- 新增 ModelResolver 解析器,按 frontmatter 中的 provider/model 名覆盖基础 LLMProviderConfig

- Expert/SubagentDef 数据结构新增 provider/model 字段,frontmatter 解析与渲染支持往返

- AgentFactory 和 DefaultSubAgentRuntime 持有 ModelResolver,在创建 agent 时解析模型覆盖

- HTTP API 新增 /api/model-options 端点,ExpertResponse/Create/Update 和 SubagentUpdateRequest 支持 provider/model

- update_expert/update_subagent 支持 provider/model 字段写回 frontmatter

- 保持架构解耦:ModelResolver 位于 config 底层,不引入新的跨模块依赖
2026-07-30 22:44:10 +08:00
oudecheng
c27efedb6c feat(capability): 扩展 CapabilityPolicy 支持子代理黑白名单
- domain: CapabilityPolicy 新增 allowed_subagents/denied_subagents 字段及 check_subagent_allowed 方法
- experts: 专家 frontmatter 解析/渲染支持子代理策略字段
- task/runtime: spawn/resume 双路径校验父代理子代理策略;新增 update_subagent 写回 SUBAGENT.md(与 update_expert 对称);新增 SubagentPromptProvider 按专家策略过滤子代理索引
- task/runtime: 子代理自身 capability 作为孙代理的 parent_capability 透传(ToolContext),保持解耦
- traits: ToolContext 新增 parent_capability 字段
- agent_factory: 主 agent 注入 expert_capability 到 ToolContext

安全:策略不通过即拒绝(与 def 不可用即拒绝范式一致),防止 LLM 通过选择被禁子代理绕过限制;max_nesting_depth 兜底防递归不可被 def 覆盖。
2026-07-30 17:37:29 +08:00
oudecheng
12f1094426 feat(capability): 新增 CapabilityPolicy 统一策略模型并集成至专家/子代理/技能
- domain: 定义 CapabilityPolicy(allowed/denied skills/tools)统一策略结构

- experts: 专家支持 capability 字段,新增 update_expert 写回 EXPERT.md

- skills: SkillRuntime 暴露 capability 过滤接口

- tools/task: SubagentDef 增加 capability 字段,SubagentRuntime 新增 update_subagent 写回 SUBAGENT.md,工具集按 capability 过滤

- agent_factory: 按 capability 构建专家/子代理工具集(白名单交集 + 黑名单扣除)
2026-07-30 16:53:30 +08:00
56612389ae 改用gray_matter解析md头元数据,增加相应的日志 2026-07-21 16:33:55 +08:00
oudecheng
0a8d21fe40 fix: 修复专家发现与前端选择多项问题
后端:
- split_frontmatter 兼容 CRLF/LF 行尾符,修复 Windows 下 EXPERT.md 解析失败
- Config::load_from 移除 fallback 到 cwd/config.json 的逻辑,避免静默加载项目目录配置导致 experts 字段缺失
- ExpertRuntime 新增 update_config 方法,save_config 时同步更新 ExpertRuntime 内部 config,sources 变更即时生效
- source_order 空数组不再兜底返回 [User, Project],尊重用户关闭所有源的意图
- from_config_with_cwd 增加诊断日志,输出 enabled/sources/cwd/discovered

前端:
- ExpertSelector 弹窗改为按钮上方居中展开
- 专家卡片 name 完整显示(break-all),路径显示在卡片底部
- "管理专家"入口仅在无专家时显示
- 每次打开下拉都重新拉取列表和选中状态
- 监听设置弹窗关闭事件刷新已选专家(处理已选专家被禁用的情况)
2026-07-08 14:53:30 +08:00
oudecheng
7eecd0b6bb feat: 专家配置保存后即时生效,无需重启网关
experts/mod.rs: config 改为 RwLock 支持 update_config 运行时更新; ExpertWithStatus 增加 body 字段供前端编辑模态框直接显示; 空 sources 时不再兜底返回 [User,Project],尊重用户关闭所有源的意图。

gateway/http.rs: save_config 同步调用 experts.update_config,返回消息从'需要重启'改为'已保存'。

ConfigPage.tsx: 编辑模态框宽度扩大到 max-w-3xl,textarea 高度增加到 360px,提示文案明确正文与名称/描述的注入关系。
2026-07-07 14:13:09 +08:00
oudecheng
c2d9bf8b5e feat: 新增专家提示词核心模块,支持文件发现、CRUD与运行时选择
- 新增 src/experts/mod.rs 模块,镜像 skills/subagents 模式

- 支持 user/project 双 scope 从 EXPERT.md 文件发现专家

- ExpertRuntime 维护 session→expert 映射与禁用列表,持久化到 expert-state.json

- ExpertPromptProvider 实现系统提示词注入,未选中时返回 None

- 包含 16 个单元测试覆盖 frontmatter 解析、discover 优先级、CRUD、select/clear、disable 场景
2026-07-06 18:07:10 +08:00