---
title: "日历能力缺失修复 + UI 布局优化 + 会话 404 处理"
date: 2026-06-28
category: docs/solutions/logic-errors
module: tools/calendar_tool, server/app, server/routes/portal, frontend/stores/chat
problem_type: logic_error
component: service_object
symptoms:
  - "LLM 回复'我没有提醒功能'，不调用 calendar 工具创建事件"
  - "calendar_tool 构建 reminder_rules 但未传入 service.create_event，提醒规则被静默丢弃"
  - "default agent 在 CalendarTool 注册前创建，系统提示中缺少 calendar 工具描述"
  - "系统提示出现重复的 '## 可用工具' 段落"
  - "deleteConversation 未清理 pendingConversations，删除进行中的会话导致状态泄漏"
  - "404 处理器递归调用 selectConversation 无保护，多会话过期时级联触发 N 次网络请求"
  - "右侧面板收起按钮未垂直居中"
  - "SystemMonitorPanel monitor 标签页缺少 flex 布局，滚动和垂直居中失效"
  - "WS connected 事件在 ID 不变时未清除 is_local 标志"
  - "gui_mode 变量在 lifespan 中未定义（F821）"
root_cause: logic_error
resolution_type: code_fix
severity: high
tags: [code-review, calendar, reminder, websocket, system-prompt, ui-layout, state-management]
---

# 日历能力缺失修复 + UI 布局优化 + 会话 404 处理

## Problem

用户报告三个问题：(1) AI 无法响应定时提醒请求（"下周一提醒我准备项目启动会材料"），回复"我没有这个能力"；(2) 右侧面板收起按钮未垂直居中；(3) 会话 404 错误导致 UI 异常。代码审查发现 16 个问题（1 P0、2 P1、6 P2、7 P3），核心根因是 CalendarTool 未正确接入 ReAct agent 的工具链。

## Symptoms

- **日历能力完全失效（P0）**：`calendar_tool.py` 第 164-175 行构建了 `reminder_rules`，但第 190-203 行调用 `service.create_event` 时未传递该参数——提醒规则被静默丢弃，提醒永远不会触发。
- **LLM 看不到 calendar 工具（P2）**：`default` agent 在 CalendarTool 注册前创建，缓存的工具集和系统提示中都没有 `calendar`。即使后续注册了 CalendarTool 到 `tool_registry`，agent 的 `_system_prompt` 已固化。
- **系统提示重复段落（P2）**：附加 CalendarTool 时读取已含"## 可用工具"的 `_system_prompt` 作为 `base_prompt`，再拼接新的"## 可用工具"，产生两个重复段落。
- **删除会话状态泄漏（P1）**：`deleteConversation` 未调用 `markConversationDone`，pending 状态残留。后端迟到的 result 事件可能被错误路由到新会话。
- **404 级联（P1）**：多个会话过期时，404 处理器递归调用 `selectConversation` 无保护，导致 N 次顺序网络请求和 UI 卡顿。
- **monitor 标签页布局失效（P2）**：容器 div 缺少 `display: flex; flex-direction: column`，子元素的 `flex: 1` 和 `overflow-y: auto` 不生效。

## Root Cause

### 日历能力断裂的完整因果链

1. `lifespan` 启动时先创建 `default` agent（第 177 行），此时 CalendarTool 尚未注册
2. agent 的 `_system_prompt` 在创建时通过 `_build_tools_description` 固化，不含 calendar 工具
3. 日历子系统初始化（第 438 行）注册 CalendarTool 到 `app.state.tool_registry`
4. 但 `default` agent 已缓存的 `_tool_registry` 和 `_system_prompt` 不会自动更新
5. LLM 在 ReAct 循环中看不到 calendar 工具，回复"我没有这个能力"
6. 即使 LLM 调用了 calendar 工具，`reminder_rules` 未传入 `create_event`，提醒不会触发

### 修复方案

1. **P0**：在 `calendar_tool.py` 的 `create_event` 调用中添加 `reminder_rules=reminder_rules` 参数；添加 `reminder_offset_minutes` 范围校验（0-43200）
2. **P2**：在 `app.py` 中注册 CalendarTool 后，将其追加到 `default` agent 的 `_tool_registry`，剥离已有"## 可用工具"段落后重新拼接系统提示
3. **P1**：`deleteConversation` 添加 `markConversationDone(id)` 清理 pending 状态，跳过 `is_local` 会话的 API 调用，删除当前会话时自动切换
4. **P1**：404 处理器添加 `_is404Recovering` 递归保护标志
5. **P2**：`SystemMonitorPanel` monitor 容器添加 `display: flex; flex-direction: column`
6. **P3**：`PortalConnectionManager.send_json` 遍历前快照列表；WS `connected` 无条件清除 `is_local`；移除 `if(calendarStore)` 死代码

## Verification

- `ruff check` 通过（修复了 `gui_mode` F821 未定义错误）
- `pytest tests/unit/calendar/` — 98 passed
- `npm run typecheck` — 通过

## Files Changed

| 文件 | 修复内容 |
|------|----------|
| `src/agentkit/tools/calendar_tool.py` | P0: 传递 reminder_rules + 范围校验 |
| `src/agentkit/server/app.py` | P2: 附加 CalendarTool 到 default agent + 剥离重复段落 + 修复 gui_mode F821 |
| `src/agentkit/server/frontend/src/stores/chat.ts` | P1: deleteConversation 清理 + 404 递归保护 + WS connected 清除 is_local + 移除死代码 |
| `src/agentkit/server/routes/portal.py` | P3: send_json 快照列表 |
| `src/agentkit/server/frontend/src/components/layout/SystemMonitorPanel.vue` | P2: monitor flex 布局 |
