feat(agent): ✨ 在 Agent 聊天接口中新增 AI 随口记功能 * 无相关意图时保持正常聊天,若识别到相关意图则自动切换为随口记模式 * 支持阶段状态反馈与话题化回复,提升交互体验 - 引入请求级当前时间基准,支持相对时间解析(如“明天”、“下周一”等) - 增加非法日期拦截机制,防止用户输入格式错误的时间并返回修正提示 - 优化随口记图谱,补充阶段打点与详细中文注释,失败/重试分支处理更清晰 - 推送 `reasoning_content` 阶段状态,涵盖 `request.accepted`、`intent`、`deadline`、`priority`、`persisting`、`persisted`、`reply.polishing` 等状态 - 最终文案改为“事实句 + AI 生成的贴题轻松跟进句”,避免硬编码调侃内容 - 完善时间解析相关测试,确保功能正确性,测试通过 `go test ./...` --- improvements: 🛠️ 开发心路历程与优化 * 修复随口记链路中 `assistant` 消息未写入 Redis 的问题,确保消息持久化 * 去除“分段正文伪流式”处理,改为最终正文一次性输出,简化内容流转
124 lines
3.4 KiB
Go
124 lines
3.4 KiB
Go
package agent
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestParseOptionalDeadlineWithNow_Absolute(t *testing.T) {
|
|
loc := quickNoteLocation()
|
|
now := time.Date(2026, 3, 12, 10, 15, 0, 0, loc)
|
|
|
|
deadline, err := parseOptionalDeadlineWithNow("2026-03-20 18:30", now)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if deadline == nil {
|
|
t.Fatalf("deadline should not be nil")
|
|
}
|
|
|
|
want := time.Date(2026, 3, 20, 18, 30, 0, 0, loc)
|
|
if !deadline.Equal(want) {
|
|
t.Fatalf("unexpected deadline, got=%s want=%s", deadline.Format(time.RFC3339), want.Format(time.RFC3339))
|
|
}
|
|
}
|
|
|
|
func TestParseOptionalDeadlineWithNow_RelativeTomorrowWithoutClock(t *testing.T) {
|
|
loc := quickNoteLocation()
|
|
now := time.Date(2026, 3, 12, 10, 15, 0, 0, loc)
|
|
|
|
deadline, err := parseOptionalDeadlineWithNow("明天交计网实验报告", now)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if deadline == nil {
|
|
t.Fatalf("deadline should not be nil")
|
|
}
|
|
|
|
want := time.Date(2026, 3, 13, 23, 59, 0, 0, loc)
|
|
if !deadline.Equal(want) {
|
|
t.Fatalf("unexpected deadline, got=%s want=%s", deadline.Format(time.RFC3339), want.Format(time.RFC3339))
|
|
}
|
|
}
|
|
|
|
func TestParseOptionalDeadlineWithNow_RelativeTomorrowWithClock(t *testing.T) {
|
|
loc := quickNoteLocation()
|
|
now := time.Date(2026, 3, 12, 10, 15, 0, 0, loc)
|
|
|
|
deadline, err := parseOptionalDeadlineWithNow("明天下午3点交计网实验报告", now)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if deadline == nil {
|
|
t.Fatalf("deadline should not be nil")
|
|
}
|
|
|
|
want := time.Date(2026, 3, 13, 15, 0, 0, 0, loc)
|
|
if !deadline.Equal(want) {
|
|
t.Fatalf("unexpected deadline, got=%s want=%s", deadline.Format(time.RFC3339), want.Format(time.RFC3339))
|
|
}
|
|
}
|
|
|
|
func TestParseOptionalDeadlineWithNow_RelativeWeekday(t *testing.T) {
|
|
loc := quickNoteLocation()
|
|
now := time.Date(2026, 3, 12, 10, 15, 0, 0, loc) // 周四
|
|
|
|
deadline, err := parseOptionalDeadlineWithNow("下周一上午9点开组会", now)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if deadline == nil {
|
|
t.Fatalf("deadline should not be nil")
|
|
}
|
|
|
|
want := time.Date(2026, 3, 16, 9, 0, 0, 0, loc)
|
|
if !deadline.Equal(want) {
|
|
t.Fatalf("unexpected deadline, got=%s want=%s", deadline.Format(time.RFC3339), want.Format(time.RFC3339))
|
|
}
|
|
}
|
|
|
|
func TestParseOptionalDeadlineFromUserInput_NoHint(t *testing.T) {
|
|
loc := quickNoteLocation()
|
|
now := time.Date(2026, 3, 12, 10, 15, 0, 0, loc)
|
|
|
|
deadline, hasHint, err := parseOptionalDeadlineFromUserInput("帮我记一下要复习计网", now)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if hasHint {
|
|
t.Fatalf("expected no time hint")
|
|
}
|
|
if deadline != nil {
|
|
t.Fatalf("deadline should be nil when no time hint")
|
|
}
|
|
}
|
|
|
|
func TestParseOptionalDeadlineFromUserInput_InvalidDate(t *testing.T) {
|
|
loc := quickNoteLocation()
|
|
now := time.Date(2026, 3, 12, 10, 15, 0, 0, loc)
|
|
|
|
deadline, hasHint, err := parseOptionalDeadlineFromUserInput("2026-13-45 25:99 交实验", now)
|
|
if err == nil {
|
|
t.Fatalf("expected error but got nil")
|
|
}
|
|
if !hasHint {
|
|
t.Fatalf("expected hasHint=true")
|
|
}
|
|
if deadline != nil {
|
|
t.Fatalf("deadline should be nil for invalid date")
|
|
}
|
|
}
|
|
|
|
func TestParseOptionalDeadlineWithNow_Invalid(t *testing.T) {
|
|
loc := quickNoteLocation()
|
|
now := time.Date(2026, 3, 12, 10, 15, 0, 0, loc)
|
|
|
|
deadline, err := parseOptionalDeadlineWithNow("记得尽快处理", now)
|
|
if err == nil {
|
|
t.Fatalf("expected error but got nil")
|
|
}
|
|
if deadline != nil {
|
|
t.Fatalf("deadline should be nil for invalid input")
|
|
}
|
|
}
|