feat: 子任务默认模型/强度(child_model/child_effort)
主任务可显式声明派生默认,或在 prompt 里写“子任务用 gpt-6-luna max” 由服务端解析填入;marker task-create 与协调员分工未显式写模型/强度时 按 块/分工 > 派生默认 > 父任务模型/强度 继承,fork 复制派生默认, continue 可改派生默认;console 新建/继续表单与任务详情同步展示。
This commit is contained in:
1 parent
f99e667222
commit
14757f15c4
7 files changed
+588
-25
No files matched your search
+118
-1
@@ -25,7 +25,12 @@ wait-threads / task-cancel / task-retry。
|
||||
fork)。新任务 prompt 由标记块给,不继承父任务的历史;
|
||||
环境基线继承父任务的 environment_id,但 worker 会给它独立
|
||||
的 tenant/worktree,不动父任务的 cwd。父任务未提交的改动
|
||||
不会自动带过去。
|
||||
不会自动带过去。模型/强度继承优先级:块里显式写 >
|
||||
父任务的 child_model / child_effort(派生默认)> 父任务
|
||||
自身的 model / effort > worker 默认(NULL 时由认领方补)。
|
||||
子任务行上同时记下父任务的 child_model / child_effort,
|
||||
这样隔代派生时派生默认仍然沿用,不会因为中间一层没写
|
||||
就丢回 worker 默认。
|
||||
- task-poll / task-read:按任务 id 轮询阅读。task-poll 按
|
||||
interval 查库直到终态或超时;task-read 是同款别名,
|
||||
不传 wait_seconds 时立即读一次快照,传了则等这么久再读
|
||||
@@ -185,6 +190,118 @@ def extract_task_creates(text):
|
||||
return out
|
||||
|
||||
|
||||
_SPAWN_SUBJECT_ZH = ("新建的任务", "派生任务", "新建任务",
|
||||
"子任务", "子代理", "新任务", "新会话")
|
||||
_SPAWN_SUBJECT_EN = ("child tasks", "spawned tasks", "new tasks",
|
||||
"new sessions", "subtasks", "subtask",
|
||||
"child task", "new task", "new session")
|
||||
|
||||
|
||||
def _effort_after(text, start):
|
||||
"""在 model 后的同一子句里找强度:先找“强度/effort + 值”,
|
||||
再找紧跟 model 的裸强度词(如“gpt-6-luna max”)。子句以
|
||||
句号/换行/分号截断,跨子句的强度词不算,避免把下一句的
|
||||
词误当成这一句的强度。"""
|
||||
clause = str(text)[start:start + 60]
|
||||
for stop in ("。", "\n", ";", ";"):
|
||||
cut = clause.find(stop)
|
||||
if cut >= 0:
|
||||
clause = clause[:cut]
|
||||
labelled = re.search(
|
||||
r"(?:强度|effort)\s*[::=\s]\s*(low|medium|high|xhigh|max)",
|
||||
clause, re.IGNORECASE)
|
||||
if labelled:
|
||||
return labelled.group(1).lower()
|
||||
trailing = re.search(
|
||||
r"^\s*[,,、\s]*(low|medium|high|xhigh|max)\b",
|
||||
clause, re.IGNORECASE)
|
||||
if trailing:
|
||||
return trailing.group(1).lower()
|
||||
return None
|
||||
|
||||
|
||||
def _model_from_match(text, match, token_group):
|
||||
"""从一次正则命中里取 (model, effort):model 词本身若是
|
||||
强度词(如“子任务用 max”),只当强度、不当模型;模型词
|
||||
尾部的句点是句子标点、不是模型名的一部分,要去掉。"""
|
||||
token = match.group(token_group).rstrip(".")
|
||||
if not token:
|
||||
return None, None
|
||||
if token.lower() in EFFORTS:
|
||||
return None, token.lower()
|
||||
return token, _effort_after(text, match.end(token_group))
|
||||
|
||||
|
||||
def parse_spawn_defaults(text):
|
||||
"""从主线 prompt 里解析派生默认模型/强度,只认显式指令。
|
||||
|
||||
认的句式(主语必须是派生对象,裸说“主线用 X”不算,
|
||||
那是本任务自己的模型、应走建任务的 model 字段):
|
||||
- 中文:子任务/子代理/派生任务/新建任务/新任务/新会话 +
|
||||
用/使用/采用/模型:/模型是 + 模型词,可跟强度词或
|
||||
“强度/effort + 强度词”,如“子代理用 gpt-6-luna max”、
|
||||
“子任务模型:gpt-6-luna,强度:max”。
|
||||
- 英文:subtask/child task/spawned task/new task/session +
|
||||
use/using/with model/model: + 模型词,如
|
||||
“subtasks use gpt-6-luna with effort max”。
|
||||
- 中文倒装:用 + 模型词 + … + 子任务/子代理,如
|
||||
“用 gpt-6-luna max 跑子任务”。
|
||||
只取第一条命中;模型词只认 ASCII 词(中转模型 id 都是
|
||||
ASCII),“用默认模型”这类中文词不会被误当成模型。
|
||||
显式传了 child_model / child_effort 的任务不走本函数,
|
||||
本函数只在建任务时两者缺省才作兜底,且结果落在任务行
|
||||
的 child_model / child_effort 上、调用方可直接检查。
|
||||
返回 dict,只含解析到的键(都没解析到时为空 dict)。"""
|
||||
if not text:
|
||||
return {}
|
||||
text = str(text)
|
||||
zh_subject = "|".join(_SPAWN_SUBJECT_ZH)
|
||||
zh_pattern = re.compile(
|
||||
r"(?:%s)[^。\n;;]{0,50}?(?:用\s*|使用\s*|采用\s*"
|
||||
r"|模型\s*[::]\s*|模型\s*是\s*)"
|
||||
r"([A-Za-z][A-Za-z0-9._-]{1,63})" % zh_subject)
|
||||
match = zh_pattern.search(text)
|
||||
if match:
|
||||
model, effort = _model_from_match(text, match, 1)
|
||||
out = {}
|
||||
if model:
|
||||
out["model"] = model
|
||||
if effort:
|
||||
out["effort"] = effort
|
||||
if out:
|
||||
return out
|
||||
en_subject = "|".join(_SPAWN_SUBJECT_EN)
|
||||
en_pattern = re.compile(
|
||||
r"(?:%s)\b[^.\n]{0,50}?(?:use\s+|using\s+|with\s+model\s+"
|
||||
r"|model\s*[:=]\s*)"
|
||||
r"([A-Za-z][A-Za-z0-9._-]{1,63})" % en_subject,
|
||||
re.IGNORECASE)
|
||||
match = en_pattern.search(text)
|
||||
if match:
|
||||
model, effort = _model_from_match(text, match, 1)
|
||||
out = {}
|
||||
if model:
|
||||
out["model"] = model
|
||||
if effort:
|
||||
out["effort"] = effort
|
||||
if out:
|
||||
return out
|
||||
rev_pattern = re.compile(
|
||||
r"(?:用|使用|采用)\s*([A-Za-z][A-Za-z0-9._-]{1,63})"
|
||||
r"[^。\n;;]{0,30}?(?:%s)" % zh_subject)
|
||||
match = rev_pattern.search(text)
|
||||
if match:
|
||||
model, effort = _model_from_match(text, match, 1)
|
||||
out = {}
|
||||
if model:
|
||||
out["model"] = model
|
||||
if effort:
|
||||
out["effort"] = effort
|
||||
if out:
|
||||
return out
|
||||
return {}
|
||||
|
||||
|
||||
def extract_task_polls(text):
|
||||
"""提取 task-poll / task-read(含 read-thread 别名)块。
|
||||
|
||||
|
||||
Reference in new issue
Block a user