Version: 0.9.27.dev.260418
后端: 1. SSE 心跳保活——解决 Vite dev proxy 在 LLM thinking 静默期判 idle 断连 - api/agent.go:ChatAgent 新增 5 秒 heartbeat ticker,select 增加 heartbeat.C 分支,每 5 秒写入 SSE 注释行 : ping\n\n 并 Flush - service/agentsvc/agent_newagent.go:graph 执行失败时增加 context.Canceled / requestCtx.Err() 判断,客户端断连只记 warn 不推 errChan 也不跑 fallback,消除 "错误通道已满" 日志噪音 2. 随口记工具(quick_note_create)接入新 Agent 链路 - agent/node/quicknote.go:parseOptionalDeadlineWithNow / quickNoteLocation 首字母大写导出,供新链路复用旧链路成熟的时间解析和时区能力 - agent/node/quicknote_tool.go:parseOptionalDeadline / quickNoteLocation 同步导出,补充调用目的注释 - newAgent/tools/quicknote.go:新增 QuickNoteToolHandler,实现新链路 quick_note_create 工具的参数校验、时间解析、写库调用 - newAgent/tools/registry.go:DefaultRegistryDeps 新增 QuickNote 字段;新增 RequiresScheduleState 方法和 scheduleFreeTools 集合;注册 quick_note_create 工具(不加入 writeTools,不走 confirm 确认) - cmd/start.go:NewDefaultRegistryWithDeps 注入 QuickNote.CreateTask 闭包,捕获 taskRepo 实例写库 3. Execute 节点随口记 speak 清空 + 非 ScheduleState 工具支持 - newAgent/node/execute.go:新增非写工具 confirm→continue 自动降级逻辑;新增 quick_note_create speak 强制清空,收口统一交给 deliver,避免 execute + deliver 重复废话 - newAgent/node/execute.go:executeToolCall / executePendingTool 中 scheduleState nil 检查改为仅拦截 RequiresScheduleState 的工具;为不依赖 ScheduleState 的工具自动注入 _user_id 参数 - newAgent/prompt/execute.go:有 plan / ReAct 两套系统 prompt 中,"写操作"规则细化为"日程写操作";新增 quick_note_create 专属执行规则:speak 必须留空,收口由 deliver 完成,调用成功后可 continue 处理多任务 - newAgent/prompt/chat.go:execute 路由描述补充"记录任务/提醒"场景 前端: 1. Vite dev proxy SSE 透传配置 - vite.config.ts:/api 代理新增 configure 回调,设置 x-accel-buffering: no 和 cache-control: no-cache,禁用代理缓冲 2.SSE 流式处理修复 - AssistantPanel.vue:reasoning_content 守卫放宽,移除 !assistantMessage.content.trim() 外层条件,正文回流后仍允许追加 reasoning(工具调用摘要、阶段状态等),不再吞掉 execute/deliver 的 reasoning_content - AssistantPanel.vue:流式完成后跳过 loadConversationMessages,避免 persistVisibleMessage 尚未落库时 merge 产生重复或丢失 仓库:无
This commit is contained in:
@@ -215,7 +215,7 @@ func (n *QuickNoteNodes) Intent(ctx context.Context, st *agentmodel.QuickNoteSta
|
||||
// 2.2 先尝试吃模型返回的 deadline_at,用于减少后续重复推理。
|
||||
st.ExtractedDeadlineText = strings.TrimSpace(parsed.DeadlineAt)
|
||||
if st.ExtractedDeadlineText != "" {
|
||||
if deadline, deadlineErr := parseOptionalDeadlineWithNow(st.ExtractedDeadlineText, st.RequestNow); deadlineErr == nil {
|
||||
if deadline, deadlineErr := ParseOptionalDeadlineWithNow(st.ExtractedDeadlineText, st.RequestNow); deadlineErr == nil {
|
||||
st.ExtractedDeadline = deadline
|
||||
}
|
||||
}
|
||||
@@ -296,7 +296,7 @@ func (n *QuickNoteNodes) Priority(ctx context.Context, st *agentmodel.QuickNoteS
|
||||
st.ExtractedPriority = parsed.PriorityGroup
|
||||
st.ExtractedPriorityReason = strings.TrimSpace(parsed.Reason)
|
||||
if strings.TrimSpace(parsed.UrgencyThresholdAt) != "" {
|
||||
urgencyThreshold, thresholdErr := parseOptionalDeadlineWithNow(strings.TrimSpace(parsed.UrgencyThresholdAt), st.RequestNow)
|
||||
urgencyThreshold, thresholdErr := ParseOptionalDeadlineWithNow(strings.TrimSpace(parsed.UrgencyThresholdAt), st.RequestNow)
|
||||
if thresholdErr == nil {
|
||||
st.ExtractedUrgencyThreshold = normalizeUrgencyThreshold(urgencyThreshold, st.ExtractedDeadline)
|
||||
}
|
||||
@@ -328,11 +328,11 @@ func (n *QuickNoteNodes) Persist(ctx context.Context, st *agentmodel.QuickNoteSt
|
||||
|
||||
deadlineText := ""
|
||||
if st.ExtractedDeadline != nil {
|
||||
deadlineText = st.ExtractedDeadline.In(quickNoteLocation()).Format(time.RFC3339)
|
||||
deadlineText = st.ExtractedDeadline.In(QuickNoteLocation()).Format(time.RFC3339)
|
||||
}
|
||||
urgencyThresholdText := ""
|
||||
if st.ExtractedUrgencyThreshold != nil {
|
||||
urgencyThresholdText = st.ExtractedUrgencyThreshold.In(quickNoteLocation()).Format(time.RFC3339)
|
||||
urgencyThresholdText = st.ExtractedUrgencyThreshold.In(QuickNoteLocation()).Format(time.RFC3339)
|
||||
}
|
||||
|
||||
toolInput := QuickNoteCreateTaskToolInput{
|
||||
@@ -430,12 +430,12 @@ func planQuickNoteInSingleCall(ctx context.Context, chatModel *ark.ChatModel, no
|
||||
}
|
||||
}
|
||||
if result.DeadlineText != "" {
|
||||
if deadline, deadlineErr := parseOptionalDeadlineWithNow(result.DeadlineText, now); deadlineErr == nil {
|
||||
if deadline, deadlineErr := ParseOptionalDeadlineWithNow(result.DeadlineText, now); deadlineErr == nil {
|
||||
result.Deadline = deadline
|
||||
}
|
||||
}
|
||||
if result.UrgencyThresholdText != "" {
|
||||
if urgencyThreshold, thresholdErr := parseOptionalDeadlineWithNow(result.UrgencyThresholdText, now); thresholdErr == nil {
|
||||
if urgencyThreshold, thresholdErr := ParseOptionalDeadlineWithNow(result.UrgencyThresholdText, now); thresholdErr == nil {
|
||||
result.UrgencyThreshold = normalizeUrgencyThreshold(urgencyThreshold, result.Deadline)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,11 +138,11 @@ func BuildQuickNoteToolBundle(ctx context.Context, deps QuickNoteToolDeps) (*Qui
|
||||
return nil, fmt.Errorf("priority_group=%d 非法,必须在 1~4", input.PriorityGroup)
|
||||
}
|
||||
|
||||
deadline, err := parseOptionalDeadline(input.DeadlineAt)
|
||||
deadline, err := ParseOptionalDeadline(input.DeadlineAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
urgencyThresholdAt, err := parseOptionalDeadline(input.UrgencyThresholdAt)
|
||||
urgencyThresholdAt, err := ParseOptionalDeadline(input.UrgencyThresholdAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -180,9 +180,9 @@ func BuildQuickNoteToolBundle(ctx context.Context, deps QuickNoteToolDeps) (*Qui
|
||||
|
||||
deadlineStr := ""
|
||||
if result.DeadlineAt != nil {
|
||||
deadlineStr = result.DeadlineAt.In(quickNoteLocation()).Format(time.RFC3339)
|
||||
deadlineStr = result.DeadlineAt.In(QuickNoteLocation()).Format(time.RFC3339)
|
||||
} else if deadline != nil {
|
||||
deadlineStr = deadline.In(quickNoteLocation()).Format(time.RFC3339)
|
||||
deadlineStr = deadline.In(QuickNoteLocation()).Format(time.RFC3339)
|
||||
}
|
||||
|
||||
return &QuickNoteCreateTaskToolOutput{
|
||||
@@ -219,8 +219,9 @@ func GetInvokableToolByName(bundle *QuickNoteToolBundle, name string) (tool.Invo
|
||||
return getInvokableToolByName(bundle.Tools, bundle.ToolInfos, name)
|
||||
}
|
||||
|
||||
// parseOptionalDeadline 解析工具输入中的可选截止时间。
|
||||
func parseOptionalDeadline(raw string) (*time.Time, error) {
|
||||
// ParseOptionalDeadline 解析工具输入中的可选截止时间。
|
||||
// 调用目的:新链路 quick_note_create 工具复用旧链路成熟的时间解析能力,支持中文相对时间。
|
||||
func ParseOptionalDeadline(raw string) (*time.Time, error) {
|
||||
value := normalizeDeadlineInput(raw)
|
||||
if value == "" {
|
||||
return nil, nil
|
||||
@@ -239,8 +240,9 @@ func parseOptionalDeadline(raw string) (*time.Time, error) {
|
||||
return deadline, nil
|
||||
}
|
||||
|
||||
// parseOptionalDeadlineWithNow 在给定时间基准下解析 deadline。
|
||||
func parseOptionalDeadlineWithNow(raw string, now time.Time) (*time.Time, error) {
|
||||
// ParseOptionalDeadlineWithNow 在给定时间基准下解析 deadline。
|
||||
// 调用目的:旧链路 intent/priority 节点在已知 now 基准下解析时间,供新链路复用。
|
||||
func ParseOptionalDeadlineWithNow(raw string, now time.Time) (*time.Time, error) {
|
||||
value := normalizeDeadlineInput(raw)
|
||||
if value == "" {
|
||||
return nil, nil
|
||||
@@ -285,7 +287,7 @@ func parseOptionalDeadlineFromText(value string, now time.Time) (*time.Time, boo
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
loc := quickNoteLocation()
|
||||
loc := QuickNoteLocation()
|
||||
now = now.In(loc)
|
||||
hasHint := hasDeadlineHint(value)
|
||||
|
||||
@@ -568,7 +570,9 @@ func resolveWeekdayDate(now time.Time, prefix string, target time.Weekday) time.
|
||||
}
|
||||
}
|
||||
|
||||
func quickNoteLocation() *time.Location {
|
||||
// QuickNoteLocation 返回随口记使用的时区(Asia/Shanghai)。
|
||||
// 调用目的:新链路 quick_note_create 工具格式化时间输出时复用。
|
||||
func QuickNoteLocation() *time.Location {
|
||||
loc, err := time.LoadLocation(agentmodel.QuickNoteTimezoneName)
|
||||
if err != nil {
|
||||
return time.Local
|
||||
@@ -581,5 +585,5 @@ func quickNoteNowToMinute() time.Time {
|
||||
}
|
||||
|
||||
func formatQuickNoteTimeToMinute(t time.Time) string {
|
||||
return agentshared.FormatMinute(t.In(quickNoteLocation()))
|
||||
return agentshared.FormatMinute(t.In(QuickNoteLocation()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user