Files
7418andClaude Opus 4.6 19aba25c8f feat: assistant workspace — persistent AI personality & memory via Markdown files (#165)
Add "Assistant Workspace" feature that lets users designate a directory
(e.g. Obsidian vault) containing 4 Markdown files (soul.md, user.md,
memory.md, claude.md) to define AI personality, user profile, long-term
memory, and execution rules. These files are automatically injected into
the system prompt for assistant project sessions.

Core library (src/lib/assistant-workspace.ts):
- Workspace validation, initialization with template files
- File loading with 8000-char truncation, XML prompt assembly (40k limit)
- State management via .assistant/state.json
- Directory docs generation (README.ai.md + PATH.ai.md)
- Case-insensitive file name fallback (soul.md → SOUL.md)

System prompt injection (src/app/api/chat/route.ts):
- Scoped to sessions where working_directory === workspace path
- Workspace prompt prepended before session-level system prompt
- Onboarding/check-in instructions injected as <assistant-project-task>
- autoTrigger flag skips user message save and title update

Chat-based onboarding (10 questions) & daily check-in (3 questions):
- AI conducts conversation, outputs structured completion code blocks
- Frontend detects onboarding-complete/checkin-complete blocks
- Backend calls Claude API to generate file content from answers
- Fallback to raw answers if API call fails

Auto-trigger pipeline:
- Mount trigger (500ms delay) + focus fallback in MessageInput
- assistantTriggerFiredRef prevents duplicate triggers per mount
- hookTriggeredSessionId in state.json prevents cross-reload duplicates
- Daily check-in only triggers in the most recent workspace session
- hookTriggeredSessionId cleared via __clear__ sentinel after completion

API endpoints:
- GET/PUT /api/settings/workspace — path CRUD + file status
- POST /api/workspace/session — create (onboarding) or reuse (check-in)
- POST /api/workspace/onboarding — AI-generate soul.md + user.md
- POST /api/workspace/checkin — AI-update memory.md + user.md
- POST /api/workspace/hook-triggered — set/clear trigger guard
- GET /api/workspace/latest-session — latest session lookup
- POST /api/workspace/docs — refresh directory documentation

UI:
- Settings "Assistant" tab with workspace path, file status, controls
- Violet badge on workspace project group in ChatListPanel
- useAssistantWorkspace hook for state queries

Also includes:
- 102 passing tests (16 new regression tests for workspace logic)
- i18n keys for en.ts and zh.ts
- Handover documentation and execution plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:31:42 +08:00

119 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 助理工作区(Assistant Workspace)
> 创建时间:2026-03-06
> 最后更新:2026-03-06
## 状态
| Phase | 内容 | 状态 |
|-------|------|------|
| 1 | 类型定义 + 核心工作区库 | ✅ 已完成 |
| 2 | 系统提示词注入 | ✅ 已完成 |
| 3 | API 端点(workspace / onboarding / checkin / session / hook-triggered) | ✅ 已完成 |
| 4 | i18n(~48 个翻译键) | ✅ 已完成 |
| 5 | Settings UI — 助理标签页 | ✅ 已完成 |
| 6 | 对话式引导 + 自动触发 + 兜底触发 | ✅ 已完成 |
| 7 | 目录文档生成(README.ai.md + PATH.ai.md) | ✅ 已完成 |
| 8 | 回归测试(16 case) | ✅ 已完成 |
## 功能概述
用户指定一个目录(如 Obsidian vault)作为助理工作区,存放 4 份 Markdown 文件定义 AI 人格和记忆:
| 文件 | 用途 |
|------|------|
| `claude.md` | 执行规则 |
| `soul.md` | 人格风格 |
| `user.md` | 用户画像 |
| `memory.md` | 长期记忆 |
状态持久化在 `.assistant/state.json`(与目录一起可移植)。
## 架构决策
### 对话式引导(非 Dialog UI)
最初实现用 Dialog 弹窗完成引导问卷,后改为通过自然对话完成:
- 点击"开始引导"→ 创建助理项目会话 → 自动发送触发消息 → AI 逐题提问
- 输入框 focus 作为兜底触发器(防止 mount 时因各种原因未触发)
- `hookTriggeredSessionId` 状态位防止同一会话重复触发
### 确定性落盘
AI 在对话中收集完答案后输出结构化完成信号(`onboarding-complete` / `checkin-complete` 代码块),前端检测到后调用后端 API 确定性写入文件,不依赖模型自行操作文件系统。
### Prompt 作用域隔离
工作区 prompt(soul/user/memory/claude.md)仅注入 `working_directory === assistant_workspace_path` 的会话,普通项目不受影响。
### 引导与问询互斥
- `needsDailyCheckIn()` 在 `onboardingComplete === false` 时返回 false
- onboarding 完成时同时设置 `lastCheckInDate = today`,当天不再触发每日问询
### 每日问询复用会话
每日问询优先打开该工作区最后一条会话继续提问(`getLatestSessionByWorkingDirectory`),不新建会话。仅引导问卷新建会话。
## 文件清单
### 新增文件
| 文件 | 说明 |
|------|------|
| `src/lib/assistant-workspace.ts` | 核心库:文件加载/截断/拼接/状态管理/目录文档生成 |
| `src/app/api/settings/workspace/route.ts` | 工作区路径 CRUD |
| `src/app/api/workspace/onboarding/route.ts` | 引导问卷 API |
| `src/app/api/workspace/checkin/route.ts` | 每日问询 API |
| `src/app/api/workspace/session/route.ts` | 会话创建/复用(onboarding 新建,checkin 复用) |
| `src/app/api/workspace/hook-triggered/route.ts` | 防重复触发状态 API |
| `src/app/api/workspace/docs/route.ts` | 目录文档生成 API |
| `src/components/settings/AssistantWorkspaceSection.tsx` | 设置面板主组件 |
| `src/hooks/useAssistantWorkspace.ts` | 工作区状态 Hook |
| `src/__tests__/unit/assistant-workspace.test.ts` | 16 个回归测试 |
### 修改文件
| 文件 | 改动 |
|------|------|
| `src/types/index.ts` | `AssistantWorkspaceState`、`AssistantWorkspaceFiles` 接口,`SETTING_KEYS` |
| `src/app/api/chat/route.ts` | 工作区 prompt 加载(限助理项目)+ 引导/问询指令注入 |
| `src/lib/db.ts` | `getLatestSessionByWorkingDirectory()` |
| `src/components/chat/ChatView.tsx` | 自动触发 + 完成信号检测 |
| `src/components/chat/MessageInput.tsx` | focus 兜底触发 |
| `src/components/settings/SettingsLayout.tsx` | 助理标签 |
| `src/components/layout/ChatListPanel.tsx` | 助理项目徽标 |
| `src/i18n/en.ts` / `src/i18n/zh.ts` | ~48 个翻译键 |
## 数据流
```
用户点击"开始引导"
→ POST /api/workspace/session { mode: 'onboarding' }
→ 创建新会话,跳转 /chat/{id}
→ ChatView mount → checkAssistantTrigger()
→ 检测 workingDirectory === workspacePath && !onboardingComplete
→ POST /api/workspace/hook-triggered { sessionId }
→ sendMessage("请开始助理引导设置。")
→ chat/route.ts 检测 isAssistantProject + !state.onboardingComplete
→ 注入 onboarding 系统提示
→ AI 逐题提问,用户逐题回答
→ AI 输出 ```onboarding-complete {...}```
→ ChatView.detectAssistantCompletion() 解析 JSON
→ POST /api/workspace/onboarding { answers }
→ 后端 AI 生成 soul.md + user.md → 写入文件
→ state.onboardingComplete = true, lastCheckInDate = today
```
## 测试覆盖
| 测试 | 验证行为 |
|------|---------|
| initializeWorkspace creates state.json | 初始化写入 state.json + 4 个模板文件 |
| onboarding auto-trigger detection | 新工作区检测到需要引导 |
| hookTriggeredSessionId prevents repeat | 同一会话不重复触发 |
| daily check-in respects onboarding state | 未完成引导不触发问询;完成当天不触发 |
| workspace prompt scoping | 有内容时生成 prompt,空目录返回空 |
| session reuse for daily check-in | `getLatestSessionByWorkingDirectory` 正确查询 |
| generateDirectoryDocs | 同时生成 README.ai.md 和 PATH.ai.md |