265 Commits

Author SHA1 Message Date
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
89c444ad3f feat(gateway): 新增 /api/tools 与 /api/subagents/update 端点
- /api/tools: 只读访问 ToolRegistry,返回 builtin + MCP 工具的 name/description/source

- /api/subagents/update: PUT 接口,调用 SubagentRuntime::update_subagent 写回 SUBAGENT.md frontmatter

- 路由表两处同步注册新端点
2026-07-30 16:54:19 +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
oudecheng
4baa8e7a6b fix: 内存历史按 topic_id 键化,新增 replace_topic_history 修复 DB 压缩覆盖
- SessionHistory.chat_histories 改为 topic_histories 按 topic_id 键化,消除多话题并发时内存历史互相覆盖的根因

- is_current_turn 改用 current_topic == original_topic_id 直接比较,替代失效的内存最新消息匹配判断

- 新增 ConversationRepository::replace_topic_history 按 topic 删除/插入消息,解决 replace_active_history 删除整个 session 消息的 pre-existing 问题

- compaction 路径改用 replace_topic_history,避免压缩时覆盖其他 topic 的 DB 消息

- switch_topic 不再 remove_history,不同 topic 历史独立存储互斥

- append_persisted_message 仅当 topic_id == current_topic 时更新内存,防止延迟消息污染新话题历史
2026-07-28 15:32:42 +08:00
oudecheng
b042b45ac7 fix: 话题隔离 - topic_id 全程显式传递,修复消息错投与并发阻塞
问题:WS 端一个话题执行中时新建另一话题发消息,新会话无响应
(串行锁按 chat_id 阻塞),且首个话题完成后用户消息错误出现在
旧话题而非新话题(执行路径多次从共享 UI 状态读取 topic_id 产生竞态)。

核心修复(第一性原则):
执行上下文应在消息接收时一次性捕获,全程显式传递,不从共享可变
状态重复读取。

1. processor.rs: process_one 入口捕获 current_topic,传入 handle_message
   和 set_agent_cancel_token
2. session_message_service.rs: handle_message 签名加 topic_id 参数,
   透传给 MessageExecutionRequest
3. execution.rs: MessageExecutionRequest 加 topic_id 字段;
   - 串行锁键改用 topic_id(不同 topic 并发,同 topic 串行)
   - original_topic_id 优先用传入值,消除锁等待期间 topic 切换竞态
   - append_persisted_message 调用传入 original_topic_id
   - create_agent 调用传入 original_topic_id
4. session.rs: append_persisted_message 加 explicit_topic_id 参数;
   create_agent/create_agent_with_provider_config 加 explicit_topic_id;
   set_cancel_receiver/set_agent_cancel_token 加 topic_id 参数;
   pending_cancel_tokens 查找改为优先 topic_id(避免并发 topic 执行时
   cancel token 互相覆盖)

对抗性审查补丁:
- append_persisted_message: 仅当写入 topic 匹配当前活跃 topic 时才更新
  内存历史,避免旧 topic 的排队消息污染已切换到的新 topic 内存历史
- prepare_and_execute_scheduled_task: 锁前一次性捕获 topic_id,锁后
  复用同一值作为 original_topic_id,保证锁键与写入目标一致

已验证:cargo check 通过,gateway 模块 48 个测试通过(1 个预存在的
prompt 模板测试失败,与本次修改无关)。
2026-07-28 14:19:20 +08:00
oudecheng
3a8da51936 refactor: 串行锁按 topic_id 键化,支持多话题并发执行
将 chat_serial_locks 重命名为 topic_serial_locks,串行锁粒度从
chat_id 改为 topic_id。同一 topic 的消息处理仍串行执行,不同
topic 之间互不阻塞,为后续多话题并发修复铺路。

本提交仅重命名锁结构和访问方法,调用点仍用 chat_id 作为锁键
(回退兼容),不影响现有行为。
2026-07-28 14:17:12 +08:00
oudecheng
141ffda1ee feat: 实现聊天消息的串行锁,确保同一聊天的消息处理串行执行 2026-07-15 17:47:52 +08:00
oudecheng
303f6d83e3 feat: 添加工具调用序列的前向检查,确保工具消息紧随助手消息后 2026-07-15 16:36:13 +08:00
oudecheng
cde41e32a8 refactor: 优化工具使用说明,简化记忆检索和写入规则 2026-07-13 17:00:40 +08:00
oudecheng
cea4bd3cfb feat: 子代理支持数据驱动的工具过滤(白名单+黑名单),删除内置 explore
SUBAGENT.md frontmatter 新增 denied_tools 黑名单字段,启用已有的 allowed_tools 白名单;新增 ToolRegistry::only 白名单方法;抽取 build_subagent_tools_registry(白名单→黑名单→depth 兜底);安全修复:resume 在 def 失踪时拒绝恢复而非降级为完整工具集(避免权限提升);depth 阈值改为引用 max_nesting_depth 配置;SubagentWithStatus 暴露工具字段供前端只读展示;删除内置 explore 子代理及专属 explore_max_execution_secs 配置(全栈清理);新增 23 个测试覆盖过滤矩阵、frontmatter 解析、状态投影
2026-07-09 14:42:38 +08:00
oudecheng
c276381d6c 增加整理意识,确保同类工作输出到同一文件夹 2026-07-08 16:32:43 +08:00
oudecheng
46a1ca6853 refactor: 修复 3 项 P1 技术债(硬编码 URL / any 类型 / dead_code)
P1-1: 硬编码 wechat URL 抽常量统一两处
  - config/mod.rs: 定义 pub const WECHAT_DEFAULT_BASE_URL
  - cli/init.rs: import 并引用常量,消除字面量重复
  - 消除两处不一致风险(default_wechat_base_url 与 init 向导)

P1-2: ConfigPage any 类型定义具体类型(8 处)
  - types.ts: 新增 FeishuChannelConfig/WechatChannelConfig/ChannelConfig/
    SchedulerJobConfig 类型;jobs?: any[] → SchedulerJobConfig[];
    channels: Record<string, any> → Record<string, ChannelConfig>
  - api/config.ts: 新增 RestartResponse 类型,data: any → RestartResponse
  - ConfigPage.tsx: catch (e: any) ×2 → catch (e: unknown) + 类型守卫;
    as any → as SchedulerConfig['misfire_policy'];
    Record<string, any> → Partial<ChannelConfig>;(ch: any) → (ch: ChannelConfig)

P1-3: dead_code 18 处逐一审查清理
  - 删除 10 处未使用函数/struct(YAGNI 原则):
    context_compressor.rs (into_messages, is_tool_round)
    agent_loop.rs (EmptySkillProvider struct + impl)
    memory_maintenance.rs (run_for_scope)
    session.rs (try_start/finish_background_compaction)
    session_history.rs (try_start/finish_background_compaction)
    tool_registry_factory.rs (shell_session_manager)
    task/runtime.rs (effective_allowed_tools)
  - 保留 8 处 serde 反序列化字段(删除会破坏 JSON 反序列化):
    feishu.rs/openai.rs/anthropic.rs/skills/mod.rs/task/runtime.rs
2026-07-08 14:51:42 +08:00
oudecheng
47a30e87d8 fix: 修复 http.rs 重启信号吞错(P1)
src/gateway/http.rs 的 /api/restart 处理器中:
  let _ = restart_tx.send(true);
静默丢弃了 watch::Sender::send 的错误。

若接收方任务已退出(select! 其他分支先完成),
send 返回 Err 但 HTTP 已返回 success:true,
用户误以为重启成功,实际重启未触发,且无日志可排查。

改为 if let Err(e) = ... { tracing::warn!(...) } 记录错误。
保留 200ms 延迟设计(让 HTTP 响应先返回客户端),
不改变成功路径行为,仅在失败时增加诊断日志。
2026-07-08 14:37:08 +08:00
oudecheng
fef5ae7626 fix: 修复 P0 级技术债(useEffect 依赖项缺失 + prompt 注入吞错)
P0-1: web/src/App.tsx 话题刷新 useEffect 依赖项不完整
  - 原依赖数组仅 [topicRefreshTrigger],但 effect 体内使用了
    status/handleCommand/sendMessage/requestTopicList
  - 导致断线重连后 status 从 disconnected→connected 时
    effect 不会重新运行,话题刷新被静默丢失(stale closure bug)
  - 补全依赖数组为 [topicRefreshTrigger, status, handleCommand,
    sendMessage, requestTopicList],与同文件 200-208 行 effect 风格一致

P0-2: src/gateway/agent_prompt_provider.rs 静默吞错
  - record_injection 中 let _ = repository.mark_agent_prompt_reinjected(...)
    丢弃了 Result 错误
  - 失败时 Agent prompt 注入计数错乱且无任何日志
  - 改为 if let Err(e) = ... { tracing::warn!(...) } 记录 session_id 和 error
2026-07-08 14:33:22 +08:00
oudecheng
a8267631b8 refactor: 移除未使用的 cli_sessions 变量,优化 ws.rs 中的代码 2026-07-08 09:45:20 +08:00
oudecheng
4da7b5f505 fix: TodoWriteTool merge 模式内存为空时从 DB 回填,防止丢失旧项
todo_write.rs: 内存状态为空时从 repository.list_todos 回填,保证 merge 模式不丢失旧项(进程重启后内存清空场景)。新增 MockTodoRepository 和回填测试。

tool_registry_factory.rs: TodoWriteTool::new 传入 todo_repository。
2026-07-07 14:13:56 +08:00
oudecheng
7652bb16e2 refactor: get_current/save_topic 直读 DB 加载消息,移除 SessionManager 依赖
get_current.rs 和 save_topic.rs 改为直读 DB(load_messages_for_topic),不依赖 SessionManager 内存,重启后也能正确获取历史。

mod.rs: 删除 get_messages_from_session 辅助函数。

processor.rs/ws.rs: 移除 with_session_manager 调用。
2026-07-07 14:13:31 +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
bde55cbf14 feat: 重构工具提示提供者,整合工具使用说明;删除冗余的 TodoPromptProvider 2026-07-07 10:03:16 +08:00
oudecheng
4329cfbbe9 feat: 统一路径显示格式,确保跨平台兼容性;重构系统提示词提供者构建逻辑 2026-07-07 09:19:58 +08:00
oudecheng
43f6ea7b08 feat: 新增用户附件处理规则,支持判断文件后缀并选择读取方式 2026-07-06 18:13:14 +08:00
oudecheng
9d7c1f2e52 feat: 集成专家提示词到网关配置、依赖注入与HTTP API
- config: 新增 ExpertsConfig,默认 sources=[user,project], enabled=true

- AgentFactory: 新增 experts 字段,providers 顺序为 Agent→Skill→Expert→Subagent→Todo

- GatewayState: 持有 Arc<ExpertRuntime>,from_config 中初始化

- runtime: build_session_manager_with_sender 接收 experts 参数

- 路由: 注册 7 个专家 API (list/toggle/create/update/delete/selected/select)

- http: 实现 7 个处理器,支持专家 CRUD 与 session 级选择

- session/cli: 测试便利构造器与 empty_config/build_config 补齐 experts 字段
2026-07-06 18:07:33 +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
oudecheng
8d30ccd020 feat: 新增子代理管理API,支持获取子代理列表和切换子代理状态 2026-07-06 14:41:30 +08:00
oudecheng
38b9f661ee feat: 新增技能管理API,支持获取技能列表和切换技能状态 2026-07-06 11:59:11 +08:00
oudecheng
d7ff969560 feat: 增强消息处理,清理不完整的 tool_call 序列以防止数据污染 2026-07-06 09:04:32 +08:00
oudecheng
994db87f11 feat: 新增 ExecutionCompleted 信号修复发送按钮状态
- 后端 OutboundEventKind/WsOutbound 新增 ExecutionCompleted 变体
- processor 在 handle_message 完成后发送该信号
- 飞书/微信通道过滤该信号(不发送)
- 前端 useChat 移除 stream_delta/assistant_response 的 isLoading=false
- 改由 execution_completed 事件统一设置 isLoading=false,确保智能体迭代期间按钮保持停止态
2026-07-03 19:32:14 +08:00
oudecheng
5ceafb1fd7 feat: 添加配置应用诊断日志,便于排查 AgentFactory 实例与工具列表 2026-07-03 16:33:01 +08:00
oudecheng
7640a6e5b7 fix: 修复 WebSocket 连接泄漏,使用 CancellationToken 实现优雅重启 2026-07-03 16:32:43 +08:00
oudecheng
7e24e57af4 fix: 修复 persistent_session_id 前缀重复累积问题 2026-07-03 16:32:24 +08:00
oudecheng
2a02adc7c3 feat: 将 StreamingAccumulator 中的 tool_calls 类型从 HashMap 更改为 BTreeMap;在 SkillSource 中添加自定义源支持 2026-07-03 11:34:30 +08:00
oudecheng
d2af01eb30 feat: 更新通道名称为 websocket,调整相关引用和逻辑 2026-07-03 10:58:24 +08:00
oudecheng
51e06c8f73 feat: 实现两段历史压缩的同步处理,替换会话的活动历史记录 2026-07-03 09:52:45 +08:00
oudecheng
1af0fab3ad feat: 更新配置管理,支持异步读取和写入;添加 MCP 服务器状态接口 2026-07-03 08:37:02 +08:00
oudecheng
4fabbe47e9 feat: 增强MCP集成,支持配置路径和连接重试机制 2026-06-30 10:46:33 +08:00
oudecheng
7d11ab8067 feat: 添加默认配置文件创建功能,确保首次启动时可用 2026-06-29 15:27:22 +08:00
oudecheng
26cbe7aa2d feat: 更新 created_by_message_id 逻辑,仅在内容或状态变化时进行更新 2026-06-29 15:01:32 +08:00
oudecheng
bf1549b88b feat: 优化 todo_write 工具的 merge 参数描述,调整默认值逻辑并添加测试 2026-06-29 09:24:05 +08:00
oudecheng
a40f57fb22 feat: 注册 save_topic 处理器并优化助手消息渲染逻辑 2026-06-25 14:10:04 +08:00
oudecheng
ef18500100 feat: 更新 created_by_message_id 字段的赋值逻辑,确保使用 tool_call_id 进行消息关联 2026-06-25 10:50:16 +08:00
oudecheng
c72853c79d feat: 添加 user_message_id 字段以支持用户消息的关联和同步 2026-06-24 15:13:36 +08:00
oudecheng
4efc8b51e7 feat(todo): 添加待办项关联的创建消息ID并支持消息高亮
- 在待办相关数据结构和存储中新增 created_by_message_id 字段
- 记录待办项创建时对应的消息ID,支持追溯来源
- 在前端待办列表项增加点击事件,点击后滚动并高亮对应消息
- 在消息列表组件中实现高亮动画及自动滚动功能
- 更新相关工具、协议和数据库查询,确保新字段正确传递和存储
- 增加 CSS 动画实现待办对应消息的高亮闪烁效果
- 优化前端状态管理,支持设置与获取高亮消息ID
2026-06-22 14:50:37 +08:00
oudecheng
6a496ce212 feat(task): 优化孙智能体任务消息的发送与工具注册
- 在发送任务消息时增加可选的任务仓库参数支持子任务重发
- 新增 extract_parent_task_id 函数用于提取孙智能体的父任务 ID
- 补发子任务(孙智能体)的 TaskStarted 事件,解决视图重进导致的 navigateToTaskId 丢失
- 判断并附加子任务的父任务 ID,完善日志记录与事件发送
- 在子智能体运行时根据深度排除 task 工具,防止无限嵌套调用
- ToolRegistry 新增 without 方法,可创建排除指定工具的新实例用于子智能体配置
2026-06-22 11:31:41 +08:00
oudecheng
606fcbcd29 feat(agent): 注入并传递 tool_call_id 实现任务与工具调用精准关联
- 在 agent_loop 执行上下文中注入 tool_call_id,确保执行时传递该字段
- 在 agent_factory、ws、todo_read、todo_write 等多处构造对象时添加 tool_call_id 字段初始化
- 扩展协议定义及序列化,支持 tool_call_id 字段传递
- 在工具调用任务运行时传递 tool_call_id,便于事件追踪和层级关联
- 在前端 useChat hook 增加 tool_call_id 关联逻辑,实现 task_started 事件精准匹配和跳转
- 增加 pendingTaskNavs 缓存处理,解决 task_started 事件先于 tool_call 到达的顺序问题
- 调整消息渲染逻辑,根据 tool_call_id 进行优先匹配,提升用户交互体验
2026-06-22 10:22:36 +08:00
d802534abe feat(gateway): 支持网关平滑重启功能
- 在 Gateway 运行逻辑中增加重启循环,可根据重启信号自动重启服务
- 添加取消管理器功能,支持取消所有运行中的 Agent 以便平滑重启
- 在 HTTP API 新增 /api/restart 接口,实现基于任务活动检测的安全重启
- GatewayState 增加重启信号通道,支持异步触发重启流程
- 修改主运行逻辑支持重启等待机制,实现优雅关闭或重启
- 日志初始化修复防止重复初始化导致的问题
- 技能和子代理加载支持自定义绝对路径来源,增加灵活性和扩展性
- 调整技能与子代理来源枚举,增加 Custom 选项支持动态路径
- 优化工具与任务运行时代码,完善路径处理和克隆逻辑
- 前端配置页增加时区选择下拉菜单,提供常用时区选项
- 新增来源路径编辑组件,支持启用/禁用已知来源及添加自定义绝对路径
- 配置页新增保存配置后重启提示,支持用户确认立即重启网关
- 实现重启操作的前端调用及重启状态展示,包括任务冲突提示与重启轮询恢复
- 频道绑定 Agent 字段由输入框改为下拉选择,提升配置体验和正确性
2026-06-19 10:40:00 +08:00
oudecheng
18ad891a51 feat(gateway): 补发运行中子智能体任务的TaskStarted事件
- 在加载话题历史消息时增加调用task_repository参数
- 查询该话题下所有运行中的子智能体任务
- 对每个运行中的任务补发TaskStarted事件
- 解决页面刷新后navigateToTaskId丢失的问题
- 增加错误处理及日志警告与信息输出
- 优化消息发送流程,避免子智能体消息混入
2026-06-18 19:07:26 +08:00
oudecheng
edc975e6d0 feat(command): 优化 StopExecution 命令按话题取消逻辑
- StopExecutionCommandHandler 新增 SessionManager 依赖
- 优先使用 ctx.topic_id,若无则从 SessionManager 获取当前话题
- 增加获取话题过程中错误处理和日志打印
- 更新命令处理器构造参数,传入 SessionManager
- 在命令路由和 WebSocket 注册时同步修改 StopExecutionCommandHandler 创建方式
2026-06-18 17:17:26 +08:00
oudecheng
2607ca4aa4 refactor(task): 优化任务工具和子代理深度管理
- 在 AgentContext 中新增 task_id 字段,用于标识当前智能体任务 ID
- 统一 TaskTool 构造函数,使用 Option<u32> 表示最大嵌套深度限制
- 调整子代理工具注册,适配新的 TaskTool 构造函数
- 修改子代理运行时创建逻辑,传递并设置 task_id 和 parent_task_id
- 删除重复的 task_id 提取函数,改用传递参数进行关联
- 深度校验改为判断 Option,支持无深度限制和有限层数
- 增强子代理间的任务层级关联,正确传递 parent_task_id 元数据
2026-06-18 11:41:40 +08:00
oudecheng
e506ffd539 feat(agent): 支持子孙智能体的父任务链路传递
- 在 agent_factory 和子代理相关结构体中新增 parent_task_id 字段
- 协议层序列化、反序列化及 WebSocket 适配器支持 parent_task_id 信息传递
- todo_read 与 todo_write 工具添加 parent_task_id 以保持任务层级一致
- 在 DefaultSubAgentRuntime 中实现从 session_id 提取 parent_task_id 的逻辑
- 子智能体创建孙智能体时,正确设置并传递 parent_task_id 元数据
- 前端 useChat 钩子过滤孙智能体的 TaskStarted 事件,避免视图串扰
2026-06-18 11:30:47 +08:00