补充安全权限日志与草稿状态约定
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
```text
|
||||
老板一句话
|
||||
-> AiSecretaryAgent 判断意图和上下文
|
||||
-> 意图归类为 task / reminder / qa / realtime_qa / note / need_more_info / unsupported
|
||||
-> 意图归类为 task / reminder / qa / realtime_qa / note / need_more_info / unknown / unsupported
|
||||
-> 稳定 AiSecretaryResponse JSON
|
||||
-> 生成 AI 草稿 / 追问 / 直接回复
|
||||
-> 老板确认、补充、取消或转程经理
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
- 支持老板通过飞书私聊或平台入口输入文本。
|
||||
- 统一走 `POST /api/secretary/handle-message`。
|
||||
- 判断 `task/reminder/qa/realtime_qa/note/need_more_info/unsupported`。
|
||||
- 判断 `task/reminder/qa/realtime_qa/note/need_more_info/unknown/unsupported`。
|
||||
- 生成稳定的 `AiSecretaryResponse` JSON。
|
||||
- 对任务和提醒只生成可确认草稿,不直接执行。
|
||||
- 对普通聊天、实时问答兜底、普通记录直接回复或记录。
|
||||
@@ -62,7 +62,7 @@ POST /api/secretary/handle-message
|
||||
-> 校验发送人角色
|
||||
-> 非老板直接固定回复并记录
|
||||
-> 读取 BotContext,外部 context 只作为参考
|
||||
-> 判断本次消息是 follow_up / new_request / qa / realtime_qa / note / unsupported / command
|
||||
-> 判断本次消息是 follow_up / new_request / qa / realtime_qa / note / unknown / unsupported / command
|
||||
-> 组装 PromptContext
|
||||
-> 调用模型
|
||||
-> 校验 AiSecretaryResponse
|
||||
@@ -105,7 +105,7 @@ cleared
|
||||
|
||||
- 每次进入 `awaiting_more_info` 或 `awaiting_confirm` 状态时重置 `expires_at = now + 30 分钟`。
|
||||
- 点击或说出“补充/重说”后,30 分钟内下一条消息优先尝试作为上一条草稿的修正。
|
||||
- 30 分钟内不能无条件吞掉所有消息,必须先判断为 `follow_up / new_request / qa / realtime_qa / note / unsupported / command`。
|
||||
- 30 分钟内不能无条件吞掉所有消息,必须先判断为 `follow_up / new_request / qa / realtime_qa / note / unknown / unsupported / command`。
|
||||
- 老板说“换成东东”“改到明天”“刚才那个不要了”,优先修正当前草稿。
|
||||
- 老板说“另外再安排一个”“新建一个”“再帮我记一个”,创建新草稿。
|
||||
- 老板说“确认”“就这样”“发给他”,确认当前草稿。
|
||||
@@ -113,7 +113,7 @@ cleared
|
||||
- 老板问“刚才我说了什么”“总结一下”,做上下文回顾,不修改草稿。
|
||||
- 超过 30 分钟,上下文标记 `expired`,下一条默认按新输入处理;如果老板明显仍在说上一条草稿,可先提示“上一条草稿已过期,我按新请求处理”。
|
||||
- 老板确认、取消或草稿转换为任务/提醒后立即清空上下文,不受 30 分钟窗口约束。
|
||||
- 30 分钟窗口只绑定未确认草稿;草稿进入 `CONFIRMED / CONVERTED / CANCELLED` 后,后续“改一下刚才那个”不能再修改原草稿,只能作为已发布任务/提醒变更请求或第一阶段能力外请求处理。
|
||||
- 30 分钟窗口只绑定未确认草稿;草稿进入 `confirmed / converted / cancelled / superseded / expired` 后,后续“改一下刚才那个”不能再修改原草稿,只能作为已发布任务/提醒变更请求或第一阶段能力外请求处理。
|
||||
- 多次 `follow_up` 必须合并到同一个 `pending_draft`,直到老板确认、取消、过期或明确新建,不得每次补充都新建草稿。
|
||||
- `BotContext` 只提供上下文候选,不强制绑定消息。当本地规则或模型无法判断是修改当前草稿、新建请求、普通聊天还是取消当前草稿时,必须走 `need_more_info` 追问,不允许默认修改当前草稿。
|
||||
- 老板可以通过“另外、重新来、换个事、先别管这个、取消、重新安排”等自然语言随时跳出当前上下文。
|
||||
@@ -143,7 +143,7 @@ cleared
|
||||
- 3 轮仍补不全,也生成带 `missing_fields` 的草稿,不继续拉扯。
|
||||
- 每次追问都必须保存一条 `SecretaryMessage`,`intent_type=need_more_info`,内容为本次给老板的问题。
|
||||
- 追问轮次写入 `BotContext.follow_up_count`,并记录 `OperationLog(action=ask_follow_up)`。
|
||||
- `follow_up_count` 在以下情况重置为 0:草稿被确认、取消、过期、进入 `PENDING_CONFIRM`,或生成带 `missing_fields` 的终态草稿后收到下一条新消息。
|
||||
- `follow_up_count` 在以下情况重置为 0:草稿被确认、取消、过期、进入 `pending_confirmation`,或生成带 `missing_fields` 的终态草稿后收到下一条新消息。
|
||||
|
||||
## 5. 数据对象
|
||||
|
||||
@@ -224,7 +224,7 @@ PostgreSQL 最小保存三类 AI 记忆数据:
|
||||
"message_id": "外部消息ID或内部生成ID",
|
||||
"role": "boss|assistant|system",
|
||||
"text": "原始输入或AI回复",
|
||||
"intent": "task|reminder|qa|realtime_qa|note|need_more_info|unsupported|context_summary",
|
||||
"intent": "task|reminder|qa|realtime_qa|note|need_more_info|unknown|unsupported|context_summary",
|
||||
"draft_id": "postgres_ai_draft_id",
|
||||
"bot_context_snapshot": {},
|
||||
"created_at": "2026-06-22T10:00:00+08:00"
|
||||
@@ -246,7 +246,7 @@ PostgreSQL 最小保存三类 AI 记忆数据:
|
||||
|
||||
```json
|
||||
{
|
||||
"intent": "task|reminder|qa|realtime_qa|note|need_more_info|unsupported",
|
||||
"intent": "task|reminder|qa|realtime_qa|note|need_more_info|unknown|unsupported",
|
||||
"draft_type": "task|reminder|none",
|
||||
"should_create_draft": true,
|
||||
"route_type": "none|direct_after_boss_confirm|manager_confirm_required",
|
||||
@@ -278,9 +278,9 @@ PostgreSQL 最小保存三类 AI 记忆数据:
|
||||
校验规则:
|
||||
|
||||
- `task/reminder` 必须 `should_create_draft=true`,`draft_type` 必须对应为 `task` 或 `reminder`。
|
||||
- `qa/realtime_qa/note/need_more_info/unsupported` 必须 `should_create_draft=false`,`draft_type=none`。
|
||||
- `qa/realtime_qa/note/need_more_info/unknown/unsupported` 必须 `should_create_draft=false`,`draft_type=none`。
|
||||
- `task` 时 `route_type` 必填,只能是 `direct_after_boss_confirm` 或 `manager_confirm_required`。
|
||||
- `reminder/qa/realtime_qa/note/need_more_info/unsupported` 时 `route_type=none`。
|
||||
- `reminder/qa/realtime_qa/note/need_more_info/unknown/unsupported` 时 `route_type=none`。
|
||||
- `route_type=manager_confirm_required` 时,`draft.need_manager_confirm=true`;老板主动说“给程经理看看”“让经理确认”时,也必须置为 true。
|
||||
- `route_type=direct_after_boss_confirm` 时,`draft.need_manager_confirm=false`。
|
||||
- `task` 必须有事项内容;时间不是必填项。
|
||||
@@ -314,6 +314,7 @@ PostgreSQL 最小保存三类 AI 记忆数据:
|
||||
| realtime_qa | 固定提示需要实时数据查询,第一版暂不作为正式能力 |
|
||||
| note | 只保存消息记录,不生成草稿、不通知,可用于“刚才说了什么”回顾 |
|
||||
| need_more_info | 信息不足但属于可处理范围,主动追问 |
|
||||
| unknown | 暂时无法判断意图,只允许澄清或留痕 |
|
||||
| unsupported | 超出第一版能力,解释为什么不能做,不追问执行字段 |
|
||||
|
||||
优先级和兜底规则:
|
||||
@@ -322,6 +323,7 @@ PostgreSQL 最小保存三类 AI 记忆数据:
|
||||
- `realtime_qa.answer` 固定使用模板:“这个需要实时数据查询,第一版暂不作为正式能力;我不会把它生成任务或提醒。”
|
||||
- 超出第一版能力但不属于实时数据类的输入,归为 `unsupported`。
|
||||
- `unsupported.answer` 应说明当前入口只处理老板事项草稿、提醒草稿、普通问答和普通记录,不追问执行字段。
|
||||
- `unknown.answer` 只能澄清或提示补充,不得创建事项、提醒或通知。
|
||||
|
||||
示例:
|
||||
|
||||
@@ -332,37 +334,51 @@ PostgreSQL 最小保存三类 AI 记忆数据:
|
||||
|
||||
### 5.4 草稿状态
|
||||
|
||||
`ai_drafts.status` 只表示已经落 PostgreSQL 草稿表的草稿状态。非草稿意图(`qa/realtime_qa/note/unsupported`)和纯追问结果(`need_more_info`)不落 `ai_drafts`,只保存 `SecretaryMessage`、`BotContext` 和处理结果。
|
||||
`ai_drafts.status` 只表示已经落 PostgreSQL 草稿表的草稿状态。非执行意图(`qa/realtime_qa/note/unknown/unsupported`)和纯追问结果(`need_more_info`)不得进入事项、提醒或通知闭环;如需留痕,只保存 `SecretaryMessage`、`BotContext`、`model_call_logs` 或最小草稿记录。
|
||||
|
||||
`ai_drafts.status` 建议状态:
|
||||
`ai_drafts.status` 以 `docs/contracts/状态流转约定.md` 为准,核心状态:
|
||||
|
||||
```text
|
||||
PENDING_CONFIRM
|
||||
NEED_MANAGER_CONFIRM
|
||||
CONFIRMED
|
||||
CANCELLED
|
||||
FAILED
|
||||
CONVERTED
|
||||
pending_confirmation
|
||||
awaiting_follow_up
|
||||
confirmed
|
||||
converted
|
||||
cancelled
|
||||
answered
|
||||
superseded
|
||||
expired
|
||||
parse_failed
|
||||
```
|
||||
|
||||
对老板可见时可以简化为:待确认、待程经理确认、已确认、已取消、已失败。
|
||||
对老板可见时可以简化为:待确认、等待补充、已确认、已取消、已失效、已完成、已失败。
|
||||
|
||||
状态含义:
|
||||
|
||||
- `PENDING_CONFIRM`:草稿可确认,等待老板确认。
|
||||
- `NEED_MANAGER_CONFIRM`:老板已确认,但该任务仍需要程经理确认,不能直接转换任务。
|
||||
- `CONFIRMED`:确认链路已完成,可以交给任务或提醒模块转换。
|
||||
- `CANCELLED`:老板取消草稿。
|
||||
- `FAILED`:草稿或 AI 解析过程失败的草稿状态;失败原因写入 `FailureRecord.failure_type`,例如 `ai_parse_failed`,两者不能混用。
|
||||
- `CONVERTED`:草稿已经成功转换为任务或提醒。
|
||||
- `pending_confirmation`:草稿可确认,等待老板确认、补充/重说或取消。
|
||||
- `awaiting_follow_up`:老板点击补充/重说后,等待 30 分钟内下一条消息。
|
||||
- `confirmed`:确认链路已完成,可以交给任务或提醒模块转换。
|
||||
- `converted`:草稿已经成功转换为任务或提醒;复杂事项已创建 `pending_manager_confirm` 事项壳也视为转换完成。
|
||||
- `cancelled`:老板取消草稿。
|
||||
- `answered`:已直接回复或留痕,不转换为任务或提醒。
|
||||
- `superseded`:已被补充/重说生成的新草稿替代。
|
||||
- `expired`:补充/重说等待超时,旧确认卡片不可继续使用。
|
||||
- `parse_failed`:草稿或 AI 解析过程失败,仅用于调试追踪。
|
||||
|
||||
非草稿处理状态:
|
||||
|
||||
- `need_more_info`:本轮只追问老板,不创建 `ai_drafts`;追问内容保存为 `SecretaryMessage(intent_type=need_more_info)`,上下文状态为 `BotContext.status=awaiting_more_info`。
|
||||
- `answered`:`qa/realtime_qa/note/context_summary/unsupported` 的处理结果,不转换为任务或提醒,不影响当前有效 `BotContext`。
|
||||
- 追问 3 轮仍补不全、但系统决定生成带 `missing_fields` 的草稿时,模型输出必须从 `need_more_info` 转为 `task` 或 `reminder`,创建 `PENDING_CONFIRM` 草稿,并由确认阻塞规则控制能否确认。
|
||||
- `answered`:`qa/realtime_qa/note/context_summary/unknown/unsupported` 的处理结果,不转换为任务或提醒,不影响当前有效 `BotContext`。
|
||||
- 追问 3 轮仍补不全、但系统决定生成带 `missing_fields` 的草稿时,模型输出必须从 `need_more_info` 转为 `task` 或 `reminder`,创建 `pending_confirmation` 草稿,并由确认阻塞规则控制能否确认。
|
||||
|
||||
`DRAFTING` 不作为第一版 `ai_drafts.status` 持久化枚举。实现中如需表达“AI 已决定生成草稿但还在校验/解析”的过程态,只能作为方法内的内存标记或局部变量;落库状态必须从 `PENDING_CONFIRM`、`NEED_MANAGER_CONFIRM` 或 `FAILED` 开始。
|
||||
`DRAFTING` 不作为第一版 `ai_drafts.status` 持久化枚举。实现中如需表达“AI 已决定生成草稿但还在校验/解析”的过程态,只能作为方法内的内存标记或局部变量;落库状态必须来自 `状态流转约定.md`。
|
||||
|
||||
草稿确认卡片生命周期:
|
||||
|
||||
- 每个草稿同一时间只能有一张有效确认卡片,对应 `active_card_notification_id`。
|
||||
- 老板点击“补充/重说”后,原草稿进入 `awaiting_follow_up`,原确认卡片应失效。
|
||||
- 30 分钟内收到补充消息后,新草稿 `parent_draft_id` 指向原草稿,原草稿进入 `superseded`。
|
||||
- 超过 30 分钟仍未收到补充消息时,原草稿进入 `expired`,老板下一条消息按新输入处理。
|
||||
- 飞书回调处理确认、取消、补充/重说前,必须校验回调来自当前有效卡片;旧卡片只记录事件,不写业务对象。
|
||||
|
||||
### 5.5 Prompt 硬规则
|
||||
|
||||
@@ -467,25 +483,25 @@ POST /api/secretary/handle-message
|
||||
-> 老板补充
|
||||
-> 新草稿或修订草稿
|
||||
-> 老板确认
|
||||
-> direct_after_boss_confirm: CONFIRMED -> TaskAdapter / ReminderService 转换 -> CONVERTED
|
||||
-> manager_confirm_required: NEED_MANAGER_CONFIRM -> 程经理确认 -> CONFIRMED -> TaskAdapter 转换 -> CONVERTED
|
||||
-> direct_after_boss_confirm: confirmed -> TaskAdapter / ReminderService 转换 -> converted
|
||||
-> manager_confirm_required: confirmed -> 创建 pending_manager_confirm 事项壳 -> converted -> 程经理确认后通知接收人
|
||||
```
|
||||
|
||||
草稿确认后的边界:
|
||||
|
||||
- `direct_after_boss_confirm`:老板确认成功后,草稿进入 `CONFIRMED`。
|
||||
- `manager_confirm_required`:老板确认成功后,草稿进入 `NEED_MANAGER_CONFIRM`,通知或展示给程经理确认;程经理确认后才进入 `CONFIRMED`。
|
||||
- 任务/提醒转换成功后,草稿进入 `CONVERTED`,并清空 `BotContext`。
|
||||
- 任务/提醒转换失败时,不回滚老板确认;草稿保持 `CONFIRMED`,写 `FailureRecord(draft_convert_failed)`,支持后台重试或人工处理。
|
||||
- 老板确认后,无论进入 `CONFIRMED` 还是 `NEED_MANAGER_CONFIRM`,都要清空老板侧 `BotContext`;后续经理确认不再依赖老板 30 分钟上下文。
|
||||
- `NEED_MANAGER_CONFIRM / CONFIRMED / CONVERTED` 后,01 不再直接修改原草稿;老板后续说“把刚才发出去那个改一下”,应识别为任务/提醒变更请求,第一阶段未接入变更能力时回复暂不支持或引导到任务模块。
|
||||
- `direct_after_boss_confirm`:老板确认成功后,草稿进入 `confirmed`,转换成功后进入 `converted`。
|
||||
- `manager_confirm_required`:老板确认成功后,草稿进入 `confirmed`;转换时先创建 `tasks.status=pending_manager_confirm` 的事项壳,并给程经理发送待确认提醒;事项壳创建成功后草稿进入 `converted`。
|
||||
- 程经理确认复杂事项时,补齐接收人、内容和通知信息,使事项进入 `pending_notify`,再通知接收人。
|
||||
- 任务/提醒转换失败时,不回滚老板确认;草稿保持 `confirmed`,写 `FailureRecord(draft_convert_failed)`,支持后台重试或人工处理。
|
||||
- 老板确认后要清空老板侧 `BotContext`;后续经理确认不再依赖老板 30 分钟上下文。
|
||||
- `confirmed / converted / cancelled / superseded / expired` 后,01 不再直接修改原草稿;老板后续说“把刚才发出去那个改一下”,应识别为任务/提醒变更请求,第一阶段未接入变更能力时回复暂不支持或引导到任务模块。
|
||||
|
||||
直接回复流转:
|
||||
|
||||
```text
|
||||
qa / realtime_qa / note / context_summary
|
||||
qa / realtime_qa / note / unknown / context_summary
|
||||
-> answered 处理结果
|
||||
-> 不落 ai_drafts,不转换,不清空当前有效 BotContext
|
||||
-> 不进入事项、提醒或通知闭环,不清空当前有效 BotContext
|
||||
```
|
||||
|
||||
`context_summary` 也必须保存为一条 `SecretaryMessage(intent_type=context_summary)`,便于调试页回看“老板什么时候要求回顾、系统回了什么”。
|
||||
@@ -500,17 +516,17 @@ qa / realtime_qa / note / context_summary
|
||||
|
||||
JSON 非法 / schema 校验失败
|
||||
-> 不创建可确认草稿
|
||||
-> 可选创建 FAILED 草稿仅用于调试
|
||||
-> 可选创建 parse_failed 草稿仅用于调试;如果无法创建最小草稿,failure_records.target_type 使用 model_call_log
|
||||
-> FailureRecord(ai_parse_failed)
|
||||
```
|
||||
|
||||
`FAILED` 草稿不能确认、不能转换为任务/提醒、不能发送通知,只能用于调试追踪。
|
||||
`parse_failed` 草稿不能确认、不能转换为任务/提醒、不能发送通知,只能用于调试追踪。
|
||||
|
||||
取消流转:
|
||||
|
||||
```text
|
||||
PENDING_CONFIRM
|
||||
-> CANCELLED
|
||||
pending_confirmation
|
||||
-> cancelled
|
||||
-> 清空 BotContext
|
||||
|
||||
awaiting_more_info 且还没有 ai_drafts
|
||||
@@ -518,7 +534,7 @@ awaiting_more_info 且还没有 ai_drafts
|
||||
-> 记录 OperationLog(cancel_context)
|
||||
```
|
||||
|
||||
`NEED_MANAGER_CONFIRM` 阶段如需取消或退回,归程经理确认模块或任务模块处理;01 只负责展示状态和记录操作,不再把它当作可补充草稿处理。
|
||||
复杂事项壳 `pending_manager_confirm` 阶段如需取消或退回,归程经理确认模块或任务模块处理;01 只负责展示草稿来源和记录操作,不再把它当作可补充草稿处理。
|
||||
|
||||
## 9. 失败和日志
|
||||
|
||||
@@ -756,7 +772,7 @@ awaiting_more_info 且还没有 ai_drafts
|
||||
- 返回 `reply_type=error`。
|
||||
- `answer=暂时没处理好,请稍后再试。`
|
||||
- `failure.type=ai_parse_failed`。
|
||||
- 如落 `FAILED` 草稿,仅用于调试,不能确认或转换。
|
||||
- 如落 `parse_failed` 草稿,仅用于调试,不能确认或转换。
|
||||
|
||||
### 10.15 低置信度追问
|
||||
|
||||
@@ -776,7 +792,7 @@ awaiting_more_info 且还没有 ai_drafts
|
||||
|
||||
### 10.16 已发布后修改
|
||||
|
||||
前置:上一条草稿已经 `CONVERTED`,`BotContext` 已清空。
|
||||
前置:上一条草稿已经 `converted`,`BotContext` 已清空。
|
||||
|
||||
输入:
|
||||
|
||||
@@ -864,10 +880,10 @@ awaiting_more_info 且还没有 ai_drafts
|
||||
|
||||
期望:
|
||||
|
||||
- 老板确认后草稿进入 `NEED_MANAGER_CONFIRM`。
|
||||
- 老板确认后草稿进入 `confirmed`。
|
||||
- 清空老板侧 `BotContext`。
|
||||
- 不直接调用 `TaskAdapter` 转换任务。
|
||||
- 程经理确认后草稿进入 `CONFIRMED`,再转换为任务并进入 `CONVERTED`。
|
||||
- 创建 `tasks.status=pending_manager_confirm` 的事项壳,不直接通知最终接收人。
|
||||
- 程经理确认后,事项壳进入 `pending_notify` 并通知接收人;草稿在事项壳创建成功后进入 `converted`。
|
||||
|
||||
## 11. Review 重点
|
||||
|
||||
@@ -880,7 +896,7 @@ awaiting_more_info 且还没有 ai_drafts
|
||||
- 是否低置信度时追问老板,而不是默认修改当前草稿。
|
||||
- 是否 `ai_drafts.status` 和非草稿处理状态已经拆清,`need_more_info/answered` 不误落草稿表。
|
||||
- 是否所有 AI 输出都做 JSON 校验。
|
||||
- 是否 `qa/realtime_qa/note/need_more_info/unsupported` 没有误生成草稿。
|
||||
- 是否 `qa/realtime_qa/note/need_more_info/unknown/unsupported` 没有误进入事项、提醒或通知闭环。
|
||||
- 是否普通任务不强制时间。
|
||||
- 是否提醒缺时间会追问。
|
||||
- 是否 AI 只生成草稿,不直接执行。
|
||||
@@ -907,8 +923,8 @@ awaiting_more_info 且还没有 ai_drafts
|
||||
- 是否 `secretary_messages` 只追加、`bot_contexts` 可覆盖、`bot_context_snapshot` 不作为最新状态。
|
||||
- 是否 PostgreSQL 作为唯一事实源,AI 记忆表不替代正式草稿、任务、提醒、通知和反馈表状态。
|
||||
- 是否 PostgreSQL AI 记忆读写异常时会降级并写 `FailureRecord(memory_store_failed)` 或应用日志/告警。
|
||||
- 是否草稿 `CONFIRMED / CONVERTED / CANCELLED` 后立即清空上下文,后续修改不再直接改原草稿。
|
||||
- 是否 `manager_confirm_required` 走 `NEED_MANAGER_CONFIRM -> 程经理确认 -> CONFIRMED -> CONVERTED`,不会绕过程经理确认。
|
||||
- 是否草稿 `confirmed / converted / cancelled / superseded / expired` 后立即清空或失效上下文,后续修改不再直接改原草稿。
|
||||
- 是否 `manager_confirm_required` 走 `confirmed -> 创建 pending_manager_confirm 事项壳 -> converted -> 程经理确认事项壳 -> pending_notify`,不会绕过程经理确认。
|
||||
- 是否转换失败写 `FailureRecord(draft_convert_failed)`,且不回滚老板确认。
|
||||
- 是否上下文回顾默认范围为最近 10 条消息、当前待确认草稿和最近 3 条已确认/已转换草稿。
|
||||
- 是否 `/api/feishu/callback` 的验签、去重和鉴权没有写进本模块。
|
||||
|
||||
Reference in New Issue
Block a user