feat: SearXNG 搜索集成 + DevTools Docker + PG 备份 + 文档更新

- web_search 工具/插件接入自托管 SearXNG,支持百度/必应/搜狗/360搜索
- DevTools 加入 docker-compose.dev.yml,devtools/Dockerfile
- scripts/pg-backup.sh 数据库备份恢复脚本,docs/pg-backup-migration.md
- 后台思考 + datetime 插件时区默认 Asia/Shanghai
- docker-compose 对齐 volume 名称,清理 tool-engine 残留引用
- README.md / Deploy.md 更新至当前架构(移除简报/tool-engine,新增搜索/跨端同步/DevTools)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 20:36:38 +08:00
parent 08687bb13d
commit b14d267642
15 changed files with 574 additions and 137 deletions
+35 -4
View File
@@ -125,6 +125,9 @@ type Thinker struct {
userOnline bool
lastOnlineChange time.Time
userSessionID string // 当前活跃的 session ID (用于重连)
// 时区设置 (默认 Asia/Shanghai,可通过 TZ 环境变量覆盖)
timeLocation *time.Location
}
// AutonomousToolPolicy 自主思考工具调用安全策略
@@ -247,6 +250,17 @@ func NewThinker(
adminSessionID string,
memClient *memory.Client,
) *Thinker {
// 加载时区配置
tzName := os.Getenv("TZ")
if tzName == "" {
tzName = "Asia/Shanghai"
}
loc, err := time.LoadLocation(tzName)
if err != nil {
log.Printf("[后台思考] 无效时区 '%s',回退到 Asia/Shanghai: %%v", tzName, err)
loc, _ = time.LoadLocation("Asia/Shanghai")
}
return &Thinker{
enabled: cfg.Enabled,
personaLoader: personaLoader,
@@ -261,6 +275,7 @@ func NewThinker(
minThinkGap: cfg.MinThinkGap,
offlineThinkGap: cfg.OfflineThinkGap,
memoryStore: memoryStore,
timeLocation: loc,
toolRegistry: toolRegistry,
convStore: convStore,
@@ -863,14 +878,30 @@ func (t *Thinker) buildThinkingUserPrompt(
var sb strings.Builder
// 注入当前现实时间,让模型对时间有感知
now := time.Now()
now := time.Now().In(t.timeLocation)
weekdayNames := []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"}
sb.WriteString(fmt.Sprintf("🕐 现在是 %s %s %02d:%02d。\n",
hour := now.Hour()
minute := now.Minute()
ampm := ""
if hour >= 0 && hour < 6 {
ampm = "凌晨"
} else if hour < 9 {
ampm = "早上"
} else if hour < 12 {
ampm = "上午"
} else if hour < 14 {
ampm = "中午"
} else if hour < 18 {
ampm = "下午"
} else {
ampm = "晚上"
}
sb.WriteString(fmt.Sprintf("🕐 现在是 %s %s %s%d:%02d (%s)。\n",
now.Format("2006年1月2日"),
weekdayNames[now.Weekday()],
now.Hour(), now.Minute()))
ampm, hour, minute,
t.timeLocation.String()))
// 根据触发原因使用不同的开场白
switch triggerReason {
case "post_chat":
sb.WriteString("开拓者刚和你聊完天。你想自然地在心里回味一下刚才的对话……\n")