feat(agent): 触发后处理可配置(运行模式/合并模式/并发上限) + 修复抽屉内下拉误关
每个自定义 agent 可配置触发后如何调度运行: - 运行模式 serial|parallel:串行排队一次一个 / 每次触发各自并发一个会话 - 合并模式 by_task|all|none(仅 serial):同任务合并 / 全部合并成一条 / 不合并 - parallel 带每 agent 最大并发上限(0=不限),超限排队等空位 实现: - DB: agents 加 trigger_run_mode/trigger_merge_mode/trigger_max_parallel 三列 (schema + 幂等 ALTER 迁移,已发版补旧库);Agent 结构/scan/SetAgentTriggerBehavior - 调度重构: triggerRun bool → triggerActive 计数 + triggerCfg 缓存; StartTriggeredRun 走 pumpLocked/runAndPump 统一泵模型,nextTriggerRun 按合并模式 取(新增 mergeAllRuns);并发安全(session 按 conv-id 隔离,已确认) - config 接口暴露/接收三字段;max_turns 改可选指针,避免触发 tab 部分 patch 清零 - 前端: 触发 tab 顶部加运行/合并模式下拉 + 最大并发输入,改动即存 修复: 抽屉(Sheet)内 Select 下拉 portal 到抽屉外,点选项/点别处被当成点击外部 误关抽屉。SelectContent 改 position=popper,并给 SheetContent 加 onInteractOutside 守卫(按 e.detail.originalEvent.target 判定弹层内点击则不关)。 Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
f9716269ea
commit
6d8fa5bc48
10 files changed
+374
-98
No files matched your search
+31
-2
@@ -132,13 +132,20 @@ type Agent struct {
|
||||
// 任务级超时收尾词(与 per-run 两套;仅 worker/planner 用);空/0=用代码内置默认。
|
||||
TaskTimeoutWrapupPrompt string `json:"task_timeout_wrapup_prompt"`
|
||||
TaskTimeoutWrapupMaxTurns int `json:"task_timeout_wrapup_max_turns"`
|
||||
// P3 触发后处理策略(仅自定义 agent 有意义):
|
||||
// TriggerRunMode serial|parallel — 串行排队 / 每次触发各自并发一个会话
|
||||
// TriggerMergeMode by_task|all|none — 仅 serial 用:同任务合并 / 全部合并 / 不合并
|
||||
// TriggerMaxParallel — 仅 parallel 用的每 agent 并发上限;0=不限
|
||||
TriggerRunMode string `json:"trigger_run_mode"`
|
||||
TriggerMergeMode string `json:"trigger_merge_mode"`
|
||||
TriggerMaxParallel int `json:"trigger_max_parallel"`
|
||||
}
|
||||
|
||||
const agentCols = `id,key,name,COALESCE(description,''),role,builtin,enabled,COALESCE(max_turns,0),COALESCE(run_seconds,600),COALESCE(web_search,false),COALESCE(interactive_shell,false),COALESCE(wrapup_prompt,''),COALESCE(wrapup_max_turns,0),COALESCE(task_timeout_wrapup_prompt,''),COALESCE(task_timeout_wrapup_max_turns,0)`
|
||||
const agentCols = `id,key,name,COALESCE(description,''),role,builtin,enabled,COALESCE(max_turns,0),COALESCE(run_seconds,600),COALESCE(web_search,false),COALESCE(interactive_shell,false),COALESCE(wrapup_prompt,''),COALESCE(wrapup_max_turns,0),COALESCE(task_timeout_wrapup_prompt,''),COALESCE(task_timeout_wrapup_max_turns,0),COALESCE(trigger_run_mode,'serial'),COALESCE(trigger_merge_mode,'by_task'),COALESCE(trigger_max_parallel,5)`
|
||||
|
||||
func scanAgent(sc interface{ Scan(...any) error }) (*Agent, error) {
|
||||
var a Agent
|
||||
err := sc.Scan(&a.ID, &a.Key, &a.Name, &a.Description, &a.Role, &a.Builtin, &a.Enabled, &a.MaxTurns, &a.RunSecs, &a.WebSearch, &a.InteractiveShell, &a.WrapupPrompt, &a.WrapupMaxTurns, &a.TaskTimeoutWrapupPrompt, &a.TaskTimeoutWrapupMaxTurns)
|
||||
err := sc.Scan(&a.ID, &a.Key, &a.Name, &a.Description, &a.Role, &a.Builtin, &a.Enabled, &a.MaxTurns, &a.RunSecs, &a.WebSearch, &a.InteractiveShell, &a.WrapupPrompt, &a.WrapupMaxTurns, &a.TaskTimeoutWrapupPrompt, &a.TaskTimeoutWrapupMaxTurns, &a.TriggerRunMode, &a.TriggerMergeMode, &a.TriggerMaxParallel)
|
||||
return &a, err
|
||||
}
|
||||
|
||||
@@ -300,6 +307,28 @@ func (d *DB) SetAgentRunSeconds(key string, runSecs int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// SetAgentTriggerBehavior stores an agent's P3 trigger post-processing策略:
|
||||
// runMode(serial|parallel) / mergeMode(by_task|all|none) / maxParallel(parallel 用,0=不限)。
|
||||
// 枚举做白名单校验,非法值回落默认,避免脏数据把调度 pump 带偏。
|
||||
func (d *DB) SetAgentTriggerBehavior(key, runMode, mergeMode string, maxParallel int) error {
|
||||
switch runMode {
|
||||
case "serial", "parallel":
|
||||
default:
|
||||
runMode = "serial"
|
||||
}
|
||||
switch mergeMode {
|
||||
case "by_task", "all", "none":
|
||||
default:
|
||||
mergeMode = "by_task"
|
||||
}
|
||||
if maxParallel < 0 {
|
||||
maxParallel = 0
|
||||
}
|
||||
_, err := d.Exec(`UPDATE agents SET trigger_run_mode=$1, trigger_merge_mode=$2, trigger_max_parallel=$3 WHERE key=$4`,
|
||||
runMode, mergeMode, maxParallel, key)
|
||||
return err
|
||||
}
|
||||
|
||||
type PromptVar struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
|
||||
@@ -269,10 +269,17 @@ CREATE TABLE IF NOT EXISTS agents (
|
||||
wrapup_max_turns INTEGER NOT NULL DEFAULT 0,
|
||||
task_timeout_wrapup_prompt TEXT NOT NULL DEFAULT '',
|
||||
task_timeout_wrapup_max_turns INTEGER NOT NULL DEFAULT 0,
|
||||
trigger_run_mode TEXT NOT NULL DEFAULT 'serial' CHECK (trigger_run_mode IN ('serial','parallel')),
|
||||
trigger_merge_mode TEXT NOT NULL DEFAULT 'by_task' CHECK (trigger_merge_mode IN ('by_task','all','none')),
|
||||
trigger_max_parallel INTEGER NOT NULL DEFAULT 5,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CONSTRAINT agents_role_ck CHECK (role IN ('goals','main','planner','worker','assistant'))
|
||||
);
|
||||
-- 加列迁移(已发版,旧库升级补列;新库 CREATE 已含。迁移不带 CHECK:旧库存量安全 + 后端写入白名单兜底)。
|
||||
ALTER TABLE agents ADD COLUMN IF NOT EXISTS trigger_run_mode TEXT NOT NULL DEFAULT 'serial';
|
||||
ALTER TABLE agents ADD COLUMN IF NOT EXISTS trigger_merge_mode TEXT NOT NULL DEFAULT 'by_task';
|
||||
ALTER TABLE agents ADD COLUMN IF NOT EXISTS trigger_max_parallel INTEGER NOT NULL DEFAULT 5;
|
||||
DROP TRIGGER IF EXISTS trg_agents_upd ON agents;
|
||||
CREATE TRIGGER trg_agents_upd BEFORE UPDATE ON agents
|
||||
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
||||
|
||||
Reference in new issue
Block a user