F2: delegate prompt tasks to native Reasoner or OpenCode backends

This commit is contained in:
Xin Wang
2026-10-23 23:46:29 +08:00
parent 529250173d
commit 16ebfe358c
14 changed files with 784 additions and 110 deletions
+29 -7
View File
@@ -7,7 +7,8 @@ from services.background_tasks.records import TERMINAL
CONTROL_NAMES = {"get_background_task", "cancel_background_task", "send_background_task_message"}
TASK_HINT = """
你可以把需要远程 coding agent 执行的工作交给后台任务工具。提交回执仅表示已接受,
你负责及时交流、澄清需求和播报进度;复杂推理或执行任务可调用 delegate_task 委派给任务后端。
任务后端拥有独立上下文,请在任务要求中提供完整目标和必要背景。提交回执仅表示已接受,
不能据此宣称代码已经修改或测试通过。后台执行时继续回答用户;查询进度用任务查询工具。
用户明确要求停止时调用取消工具,普通插话不会停止任务。收到后台任务结果后用简洁口语
告知用户一次,依据实际结果描述成功或失败。任务状态未知时如实告知,不要重复提交。
@@ -24,19 +25,40 @@ class PromptTaskBridge:
def close(self):
self._detach()
def functions(self, tool, binding):
properties, required = self.executor.schema_parts(tool, binding)
def functions(self):
backend = self.cfg.task_backend
if backend is None:
raise ValueError("助手未绑定任务后端")
source = backend.instruction_source or {"source": "model"}
model_supplied = source.get("source") == "model"
properties = {"instruction": {"type": "string", "description": "完整任务目标、必要背景和验收要求"}} if model_supplied else {}
required = ["instruction"] if model_supplied else []
async def submit(params):
if self.runtime.tool_executor_factory is not None:
await params.result_callback({"status": "error", "message": "自动测试不启动真实后台任务,请使用语音调试验证"})
return
try:
arguments = self.executor.resolve_arguments(tool, binding, params.arguments or {})
kind = source.get("source")
if kind == "model":
instruction = (params.arguments or {}).get("instruction")
elif kind == "literal":
instruction = source.get("value")
elif kind == "variable":
instruction = self.executor.store.value(str(source.get("variable_name") or source.get("variableName") or ""))
elif kind == "template":
instruction = self.executor.store.render_data(source.get("value"))
else:
raise ValueError("不支持的任务指令来源")
if not isinstance(instruction, str):
raise ValueError("任务指令必须是字符串")
result = await self.service.submit(
assistant_id=self.cfg.dynamic_variables.get("system__agent_id", ""),
conversation_id=self.cfg.conversation_id,
tool=tool, instruction=arguments["instruction"], invocation_id=params.tool_call_id,
backend=backend, instruction=instruction, invocation_id=params.tool_call_id,
variable_state={"values": self.executor.store.values,
"definitions": self.cfg.dynamic_variable_definitions,
"secrets": self.executor.store.secrets},
)
await params.result_callback({"status": "accepted", "task": result})
except ValueError as exc:
@@ -64,10 +86,10 @@ class PromptTaskBridge:
except ValueError as exc:
await params.result_callback({"status": "error", "message": str(exc)})
schemas = [(FunctionSchema(name=tool.function_name, description=tool.description or "把编程工作交给远程后台任务执行,立即返回任务编号", properties=properties, required=required), submit)]
schemas = [(FunctionSchema(name="delegate_task", description="委派复杂推理或执行任务给已配置的任务后端,立即返回任务编号", properties=properties, required=required), submit)]
for name, description in (
("get_background_task", "查询当前助手后台任务的真实进度和结果"),
("cancel_background_task", "用户明确要求停止时,请求停止远程后台任务"),
("cancel_background_task", "用户明确要求停止时,请求停止后台任务"),
("send_background_task_message", "回答后台任务当前提出的一个问题;权限确认请用户在网页操作"),
):
props = {"task_id": {"type": "string", "description": "提交回执中的任务id"}}