From 7d400afa379164e225a818717b1389a065f975ac Mon Sep 17 00:00:00 2001 From: host Date: Thu, 29 Oct 2026 17:58:50 +0800 Subject: [PATCH] console: add goal-mode invincible option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DispatchSection gains a 'goal 模式无敌版' checkbox next to 'goal 模式': checking it sends goal_mode=1 plus no_time_limit=1 (server already accepts the field; the console just never exposed it). Plain goal checkbox behavior is unchanged; invincible wins when both are checked. Plan/coordinator mutual exclusion now covers invincible too (it is a goal variant). TaskDetailPanel shows 'goal 模式无敌版(不限时)' when a task carries no_time_limit. Help text states the honest boundary: worker/docker total timeouts are lifted, the 600s single-turn host guard stays. Built with npm run build (tsc+vite pass); console.html synced verbatim from dist/index.html. --- cloud/console-react/src/api/types.ts | 3 +- .../src/sections/DispatchSection.tsx | 13 ++++-- .../src/sections/TaskDetailPanel.tsx | 2 +- cloud/console.html | 46 +++++++++---------- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/cloud/console-react/src/api/types.ts b/cloud/console-react/src/api/types.ts index dff04bb..cb11783 100644 --- a/cloud/console-react/src/api/types.ts +++ b/cloud/console-react/src/api/types.ts @@ -10,6 +10,7 @@ export interface Task { turn_id?: string; root_turn_id?: string; plan?: number | boolean; forked_from?: string; coordinator_parts?: Array<{ name: string; prompt?: string }> | null; parent_task_id?: string; coordinator_part?: string; goal_mode?: number | boolean; verify_command?: string; + no_time_limit?: number | boolean; environment_id?: string; attachments?: string[]; model?: string; effort?: string; child_model?: string; child_effort?: string; approval?: string; result_text?: string; error_text?: string; @@ -56,7 +57,7 @@ export const ROLES = ["viewer", "contributor", "maintainer", "owner"]; export interface DispatchBody { project_id: string; prompt: string; environment_id?: string; executor?: string; model?: string; effort?: string; child_model?: string; child_effort?: string; - approval?: string; plan?: number; goal_mode?: number; upload_id?: string; + approval?: string; plan?: number; goal_mode?: number; no_time_limit?: number; upload_id?: string; coordinator_parts?: Array<{ name: string; prompt?: string }>; } export interface ContinueBody { diff --git a/cloud/console-react/src/sections/DispatchSection.tsx b/cloud/console-react/src/sections/DispatchSection.tsx index 50e2032..9977084 100644 --- a/cloud/console-react/src/sections/DispatchSection.tsx +++ b/cloud/console-react/src/sections/DispatchSection.tsx @@ -9,6 +9,7 @@ export default function DispatchSection() { const [prompt, setPrompt] = useState(""); const [coordParts, setCoordParts] = useState(""); const [goalMode, setGoalMode] = useState(false); + const [goalInvincible, setGoalInvincible] = useState(false); const [planMode, setPlanMode] = useState(false); const [executor, setExecutor] = useState("docker"); const [model, setModel] = useState(""); @@ -42,15 +43,19 @@ export default function DispatchSection() { } if (planMode) { if (approval === "full") { setMsg("计划模式不能与完全访问同用"); return; } - if (goalMode) { setMsg("计划模式不能与 goal 模式同用"); return; } + if (goalMode || goalInvincible) { setMsg("计划模式不能与 goal 模式同用"); return; } body.plan = 1; } - if (goalMode) body.goal_mode = 1; + // 无敌版 = goal 模式 + 任务不限时:勾了它就同时发 goal_mode 与 + // no_time_limit(服务端已支持该字段);与普通 goal 勾选不冲突, + // 无敌版优先,单独勾普通 goal 时行为不变。 + if (goalInvincible) { body.goal_mode = 1; body.no_time_limit = 1; } + else if (goalMode) body.goal_mode = 1; const coordRaw = coordParts.trim(); if (coordRaw) { try { body.coordinator_parts = JSON.parse(coordRaw); } catch { setMsg("协调员子任务 JSON 解析失败"); return; } if (!Array.isArray(body.coordinator_parts)) { setMsg("协调员子任务必须是数组"); return; } - if (goalMode || planMode) { setMsg("协调员任务不能与 goal/计划模式同用:协调员任务本身不跑模型回合,请取消 goal/计划勾选,或清空协调员 JSON"); return; } + if (goalMode || goalInvincible || planMode) { setMsg("协调员任务不能与 goal/计划模式同用:协调员任务本身不跑模型回合,请取消 goal/计划勾选,或清空协调员 JSON"); return; } } const atts = gatherAttachments(filesRef.current?.files || null, dirRef.current?.files || null, imgRef.current?.files || null); try { @@ -74,6 +79,7 @@ export default function DispatchSection() { +