feat(agent): 新增通用 {{.Now}} 提示词变量(每轮实时渲染)
- 各 agent 渲染路径(chat/worker/mainagent/goals/planner)统一提供 Now(nowStr());
自定义会话 agent 每次触发都会重新 renderSystem,故 {{.Now}} 每轮实时刷新
- server 端 globalPromptVars + withGlobalVars:在保存校验/变量列表/预览/详情放行
{{.Now}},否则引用它的自定义提示词会被 validateTemplate 拒绝
- 无 DB 迁移(handler 层注入通用变量,不动 agent_prompt_vars 表)
- 用途:配合固定的开始时间戳相减,判断"已运行多久/是否进入最后N小时"
- 新增 agent/prompt_now_test.go:{{.Now}} 渲染实时时间、未知变量安全回退
This commit is contained in:
1 parent
7afff7e5f5
commit
7064216188
8 files changed
+86
-14
No files matched your search
+18
-3
@@ -303,6 +303,7 @@ func (s *Server) pgGetAgent(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
cur, _ := pg.CurrentPrompt(a.ID)
|
||||
vars, _ := pg.PromptVars(a.ID)
|
||||
vars = withGlobalVars(vars)
|
||||
vers, _ := pg.ListPromptVersions(a.ID)
|
||||
if vers == nil {
|
||||
vers = []db.PromptVersion{}
|
||||
@@ -339,7 +340,7 @@ func (s *Server) pgSavePrompt(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
vars, _ := pg.PromptVars(a.ID)
|
||||
if bad := validateTemplate(body.Template, vars); bad != "" {
|
||||
if bad := validateTemplate(body.Template, withGlobalVars(vars)); bad != "" {
|
||||
writeErr(w, 400, bad)
|
||||
return
|
||||
}
|
||||
@@ -495,7 +496,7 @@ func (s *Server) pgPromptVars(w http.ResponseWriter, r *http.Request) {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, 200, map[string]any{"variables": vars})
|
||||
writeJSON(w, 200, map[string]any{"variables": withGlobalVars(vars)})
|
||||
}
|
||||
|
||||
func (s *Server) pgPreviewPrompt(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -512,7 +513,7 @@ func (s *Server) pgPreviewPrompt(w http.ResponseWriter, r *http.Request) {
|
||||
if body.Template == "" {
|
||||
body.Template, _ = pg.CurrentPrompt(a.ID)
|
||||
}
|
||||
rendered, err := renderPrompt(body.Template, vars, body.Sample)
|
||||
rendered, err := renderPrompt(body.Template, withGlobalVars(vars), body.Sample)
|
||||
if err != nil {
|
||||
writeJSON(w, 200, map[string]any{"rendered": "", "error": err.Error()})
|
||||
return
|
||||
@@ -1706,6 +1707,20 @@ func (s *Server) pgListModels(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// --- prompt template helpers (Go text/template + catalog 白名单) ---
|
||||
|
||||
// globalPromptVars are runtime variables available to EVERY agent (built-in and
|
||||
// custom) regardless of its per-agent catalog. Each agent's render path fills them
|
||||
// (see agent.nowStr, rendered fresh each turn), so a prompt may always reference
|
||||
// {{.Now}} — e.g. subtract it from a fixed start stamp to reason about elapsed time.
|
||||
var globalPromptVars = []db.PromptVar{
|
||||
{Name: "Now", Description: "服务端当前时间(每次运行实时刷新;可与固定起始时间相减判断已用时长)", Example: "2026-08-11 14:30:00 CST", Source: "runtime"},
|
||||
}
|
||||
|
||||
// withGlobalVars appends the universal runtime vars onto an agent's own catalog,
|
||||
// so validation / the UI variable list / preview all recognize {{.Now}} etc.
|
||||
func withGlobalVars(vars []db.PromptVar) []db.PromptVar {
|
||||
return append(append([]db.PromptVar{}, vars...), globalPromptVars...)
|
||||
}
|
||||
|
||||
// validateTemplate parses the template and rejects any {{.Var}} not in the catalog.
|
||||
// Returns "" if valid, otherwise an error message.
|
||||
func validateTemplate(tmpl string, catalog []db.PromptVar) string {
|
||||
|
||||
Reference in new issue
Block a user