From 0f7162934b1d26a25ebdd5afa427974505ab517b Mon Sep 17 00:00:00 2001 From: host Date: Thu, 29 Oct 2026 23:36:44 +0800 Subject: [PATCH 1/2] =?UTF-8?q?console:=20=E4=BB=BB=E5=8A=A1=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=B9=9F=E6=98=BE=E7=A4=BA=E9=A6=96=E5=AD=97=E3=80=81?= =?UTF-8?q?=E6=80=BB=E8=80=97=E6=97=B6=E3=80=81token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 列表行与详情共用同一口径:新抽 api/taskMeta.ts(首字/ 总耗时/token 计算),TaskListSection 改 import 它(逻辑 原样不动),TaskDetailPanel 在状态行下方加一行:首字 方块 + 耗时 + token,title 里写口径。 详情的数据缺口一并补上:单任务接口 _get_task 此前走 _task_to_dict 默认 total_tokens=None,详情 token 只能 显示占位;现与列表一样用 _task_tokens_map 一次聚合 (单任务只多一条查询),详情直接出真数。 types.ts 里过期的“列表不回 token”注释同步更新。 新测试:单任务 GET /tasks/{id} 聚合回 total_tokens。 --- cloud/console-react/src/api/taskMeta.ts | 83 ++++++++++++++++++ cloud/console-react/src/api/types.ts | 6 +- .../src/sections/TaskDetailPanel.tsx | 5 ++ .../src/sections/TaskListSection.tsx | 87 +------------------ cloud/console.html | 22 ++--- cloud/server.py | 5 +- cloud/tests/test_task_list_tokens.py | 18 ++++ 7 files changed, 127 insertions(+), 99 deletions(-) create mode 100644 cloud/console-react/src/api/taskMeta.ts diff --git a/cloud/console-react/src/api/taskMeta.ts b/cloud/console-react/src/api/taskMeta.ts new file mode 100644 index 0000000..a164b35 --- /dev/null +++ b/cloud/console-react/src/api/taskMeta.ts @@ -0,0 +1,83 @@ +import type { Task } from "./types"; + +// 任务 meta 计算,列表行与详情共用,口径必须一致,改一处两处同变。 +// +// 首字:prompt 第一个非空白字符(按码点取,emoji 不截半); +// prompt 为空或全空白时用任务 id 首字符兜底。只作标识, +// 不改动原 prompt 文案。 +// +// 总耗时:只用任务对象已回的时间戳算,绝不编造。 +// 终态且有 started_at + finished_at:finished_at - started_at +// (与服务端项目统计 avg_duration_seconds 同口径); +// running 且有 started_at:现在 - started_at,标“进行中”, +// 数值随刷新更新,不是实时 tick; +// 无 started_at 的终态:finished_at - created_at 兜底 +// (含排队等待,口径见 title); +// 无 started_at 的 queued/running:现在 - created_at 兜底。 +// 诚实边界:worker 每次认领都会重写 started_at,所以多轮续跑 +// 任务这里显示的是末次认领的时长,不是历次认领之和;要严格 +// 累计总时长,服务端需保留首次 started_at 或累加各轮时长, +// 那是服务端字段缺口,不是前端能算出来的。 +// +// token:优先 total_tokens(列表接口由服务端一次聚合回, +// 单任务接口同样聚合回);分项只有 actual/estimated 时加总 +// 显示;都没有时显示“token —”,不编造、不估算、不逐个调 +// /cost(列表一屏 N 个任务逐个调会拖慢刷新、还容易撞限流)。 +export function firstChar(t: Task): string { + const p = (t.prompt || "").trim(); + if (p) return [...p][0]; + return t.id ? [...t.id][0] : "?"; +} + +export function formatDuration(seconds: number): string { + const s = Math.max(0, Math.floor(seconds)); + if (s < 60) return s + "秒"; + if (s < 3600) { + const m = Math.floor(s / 60), r = s % 60; + return r ? m + "分" + r + "秒" : m + "分"; + } + if (s < 86400) { + const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60); + return m ? h + "小时" + m + "分" : h + "小时"; + } + const d = Math.floor(s / 86400), h = Math.floor((s % 86400) / 3600); + return h ? d + "天" + h + "小时" : d + "天"; +} + +function num(v: number | null | undefined): number | null { + if (v === null || v === undefined) return null; + const n = Number(v); + return Number.isFinite(n) ? n : null; +} + +// 返回 [显示文案, title 口径说明];算不出时文案为“—”。 +export function durationOf(t: Task): [string, string] { + const now = Date.now() / 1000; + const started = num(t.started_at), finished = num(t.finished_at); + const created = num(t.created_at); + if (started !== null && finished !== null && finished >= started) { + return [formatDuration(finished - started), "总耗时:开始→结束(末次认领的执行时长)"]; + } + if (started !== null && t.status === "running") { + return ["进行中 " + formatDuration(now - started), "总耗时:进行中,已用时长从开始算起,随刷新更新"]; + } + if (created !== null && finished !== null && finished >= created) { + return [formatDuration(finished - created), "总耗时:创建→完成(含排队等待;无开始时间时的兜底口径)"]; + } + if (created !== null && (t.status === "queued" || t.status === "running")) { + return [(t.status === "queued" ? "排队中 " : "进行中 ") + formatDuration(now - created), "总耗时:从创建算起的已用时长(无开始时间时的兜底口径)"]; + } + return ["—", "总耗时:无可用时间戳"]; +} + +export function tokenOf(t: Task): [string, string] { + const total = num(t.total_tokens); + if (total !== null) { + return [total.toLocaleString() + " token", "token:服务端 total_tokens"]; + } + const actual = num(t.actual_tokens), estimated = num(t.estimated_tokens); + if (actual !== null || estimated !== null) { + return [((actual || 0) + (estimated || 0)).toLocaleString() + " token", "token:actual + estimated 分项加总"]; + } + return ["token —", "token:本任务对象未带 token 字段;单任务真数在详情的成本里可查,不逐个调成本接口、不编造"]; +} diff --git a/cloud/console-react/src/api/types.ts b/cloud/console-react/src/api/types.ts index d022200..9ccccbd 100644 --- a/cloud/console-react/src/api/types.ts +++ b/cloud/console-react/src/api/types.ts @@ -11,9 +11,9 @@ export interface Task { // (秒,epoch),此前 Task 类型没列、前端直接忽略了。 created_at?: number; started_at?: number | null; finished_at?: number | null; last_heartbeat?: number | null; - // token:列表接口目前不回这些字段(见 TaskListSection 的注释), - // 先留类型位:服务端一旦在列表里补 total_tokens(或 - // actual/estimated 分项),列表行无需再改代码就能显示真数。 + // token:列表与单任务接口由服务端一次聚合回 total_tokens + // (见 api/taskMeta.ts);actual/estimated 分项为成本接口 + // 的备用口径。 total_tokens?: number | null; actual_tokens?: number | null; estimated_tokens?: number | null; unpriced_actual_tokens?: number | null; turn_id?: string; root_turn_id?: string; plan?: number | boolean; forked_from?: string; diff --git a/cloud/console-react/src/sections/TaskDetailPanel.tsx b/cloud/console-react/src/sections/TaskDetailPanel.tsx index 6e5cb63..5e6c07b 100644 --- a/cloud/console-react/src/sections/TaskDetailPanel.tsx +++ b/cloud/console-react/src/sections/TaskDetailPanel.tsx @@ -2,6 +2,7 @@ import { useConsole } from "../context"; import { Card } from "../components/ui"; import { shortId, fmt } from "../api/client"; import { STATUS_EXPLAIN } from "../api/types"; +import { firstChar, durationOf, tokenOf } from "../api/taskMeta"; import DetailActions from "./detail/DetailActions"; import ReviewPanel from "./detail/ReviewPanel"; import { CoordPanel, AgentsPanel, ApprovalPanel, PeerPanel, ThreadPanel } from "./detail/DetailLists"; @@ -13,10 +14,14 @@ export default function TaskDetailPanel() { const ctx = useConsole(); const t = ctx.currentTask; if (!t) return
点任务行查看详情
; + const [dur, durTitle] = durationOf(t); + const [tok, tokTitle] = tokenOf(t); + const fc = firstChar(t); return (
状态 {t.status}({STATUS_EXPLAIN[t.status] || "未知状态"}) +
耗时 {dur} · {tok}
任务 {t.id} | turn {shortId(t.turn_id)} | root turn {shortId(t.root_turn_id)}
executor {t.executor || ""} | 主机 {t.worktree_host || ""}
模型 {t.model || "默认"} | 强度 {t.effort || "默认"} diff --git a/cloud/console-react/src/sections/TaskListSection.tsx b/cloud/console-react/src/sections/TaskListSection.tsx index cdf6fe1..d607594 100644 --- a/cloud/console-react/src/sections/TaskListSection.tsx +++ b/cloud/console-react/src/sections/TaskListSection.tsx @@ -1,90 +1,9 @@ import { useConsole } from "../context"; import { shortId } from "../api/client"; -import type { Task } from "../api/types"; +import { firstChar, durationOf, tokenOf } from "../api/taskMeta"; -// 任务列表行 meta:首字 / 总耗时 / token。 -// -// 首字:prompt 第一个非空白字符(按码点取,emoji 不截半); -// prompt 为空或全空白时用任务 id 首字符兜底。只作行前标识, -// 不改动原 prompt 文案。 -// -// 总耗时:只用列表接口已回的时间戳算,绝不编造。 -// 终态且有 started_at + finished_at:finished_at - started_at -// (与服务端项目统计 avg_duration_seconds 同口径); -// running 且有 started_at:现在 - started_at,标“进行中”, -// 数值随列表刷新更新,不是实时 tick; -// 无 started_at 的终态:finished_at - created_at 兜底 -// (含排队等待,口径见 title); -// 无 started_at 的 queued/running:现在 - created_at 兜底。 -// 诚实边界:worker 每次认领都会重写 started_at,所以多轮续跑 -// 任务这里显示的是末次认领的时长,不是历次认领之和;要严格 -// 累计总时长,服务端需保留首次 started_at 或累加各轮时长, -// 那是服务端字段缺口,不是前端能算出来的。 -// -// token:列表接口一次聚合回 total_tokens(服务端 -// _task_tokens_map:cost_records 按 task_id 求和,一屏只多 -// 一条查询)。列表行不逐个调 /cost:逐个调是一屏 N 个额外 -// 请求,会把列表刷新拖慢、还容易撞限流。分项只有 -// actual/estimated 时加总显示;都没有(非列表调用方、 -// total_tokens 为 null)时显示“token —”,不编造、不估算。 -function firstChar(t: Task): string { - const p = (t.prompt || "").trim(); - if (p) return [...p][0]; - return t.id ? [...t.id][0] : "?"; -} - -function formatDuration(seconds: number): string { - const s = Math.max(0, Math.floor(seconds)); - if (s < 60) return s + "秒"; - if (s < 3600) { - const m = Math.floor(s / 60), r = s % 60; - return r ? m + "分" + r + "秒" : m + "分"; - } - if (s < 86400) { - const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60); - return m ? h + "小时" + m + "分" : h + "小时"; - } - const d = Math.floor(s / 86400), h = Math.floor((s % 86400) / 3600); - return h ? d + "天" + h + "小时" : d + "天"; -} - -function num(v: number | null | undefined): number | null { - if (v === null || v === undefined) return null; - const n = Number(v); - return Number.isFinite(n) ? n : null; -} - -// 返回 [显示文案, title 口径说明];算不出时文案为“—”。 -function durationOf(t: Task): [string, string] { - const now = Date.now() / 1000; - const started = num(t.started_at), finished = num(t.finished_at); - const created = num(t.created_at); - if (started !== null && finished !== null && finished >= started) { - return [formatDuration(finished - started), "总耗时:开始→结束(末次认领的执行时长)"]; - } - if (started !== null && t.status === "running") { - return ["进行中 " + formatDuration(now - started), "总耗时:进行中,已用时长从开始算起,随列表刷新更新"]; - } - if (created !== null && finished !== null && finished >= created) { - return [formatDuration(finished - created), "总耗时:创建→完成(含排队等待;无开始时间时的兜底口径)"]; - } - if (created !== null && (t.status === "queued" || t.status === "running")) { - return [(t.status === "queued" ? "排队中 " : "进行中 ") + formatDuration(now - created), "总耗时:从创建算起的已用时长(无开始时间时的兜底口径)"]; - } - return ["—", "总耗时:无可用时间戳"]; -} - -function tokenOf(t: Task): [string, string] { - const total = num(t.total_tokens); - if (total !== null) { - return [total.toLocaleString() + " token", "token:服务端列表 total_tokens"]; - } - const actual = num(t.actual_tokens), estimated = num(t.estimated_tokens); - if (actual !== null || estimated !== null) { - return [((actual || 0) + (estimated || 0)).toLocaleString() + " token", "token:actual + estimated 分项加总"]; - } - return ["token —", "token:本行未带 token 字段;单任务真数在任务详情的成本里可查,本行不逐个调成本接口、不编造"]; -} +// 任务列表行 meta:首字 / 总耗时 / token,计算见 api/taskMeta.ts, +// 与任务详情共用同一口径。 // GitHub issues-style task list: search on top, the project selector // (the auto-project fix — do not remove it), a 主要聊天 header with a diff --git a/cloud/console.html b/cloud/console.html index cd38036..ca75ff5 100644 --- a/cloud/console.html +++ b/cloud/console.html @@ -12,7 +12,7 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var Ah;function Ay(){if(Ah)return ni;Ah=1;var i=Symbol.for("react.transitional.element"),r=Symbol.for("react.fragment");function m(o,_,C){var N=null;if(C!==void 0&&(N=""+C),_.key!==void 0&&(N=""+_.key),"key"in _){C={};for(var x in _)x!=="key"&&(C[x]=_[x])}else C=_;return _=C.ref,{$$typeof:i,type:o,key:N,ref:_!==void 0?_:null,props:C}}return ni.Fragment=r,ni.jsx=m,ni.jsxs=m,ni}var Mh;function My(){return Mh||(Mh=1,ar.exports=Ay()),ar.exports}var s=My(),nr={exports:{}},st={};/** + */var Ah;function zy(){if(Ah)return ni;Ah=1;var i=Symbol.for("react.transitional.element"),r=Symbol.for("react.fragment");function m(o,_,C){var N=null;if(C!==void 0&&(N=""+C),_.key!==void 0&&(N=""+_.key),"key"in _){C={};for(var x in _)x!=="key"&&(C[x]=_[x])}else C=_;return _=C.ref,{$$typeof:i,type:o,key:N,ref:_!==void 0?_:null,props:C}}return ni.Fragment=r,ni.jsx=m,ni.jsxs=m,ni}var Mh;function Ry(){return Mh||(Mh=1,ar.exports=zy()),ar.exports}var s=Ry(),nr={exports:{}},st={};/** * @license React * react.production.js * @@ -20,7 +20,7 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var Oh;function Oy(){if(Oh)return st;Oh=1;var i=Symbol.for("react.transitional.element"),r=Symbol.for("react.portal"),m=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),_=Symbol.for("react.profiler"),C=Symbol.for("react.consumer"),N=Symbol.for("react.context"),x=Symbol.for("react.forward_ref"),G=Symbol.for("react.suspense"),U=Symbol.for("react.memo"),Q=Symbol.for("react.lazy"),b=Symbol.for("react.activity"),B=Symbol.for("react.view_transition"),lt=Symbol.iterator;function at(y){return y===null||typeof y!="object"?null:(y=lt&&y[lt]||y["@@iterator"],typeof y=="function"?y:null)}var I={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},V=Object.assign,dt={};function Ot(y,R,F){this.props=y,this.context=R,this.refs=dt,this.updater=F||I}Ot.prototype.isReactComponent={},Ot.prototype.setState=function(y,R){if(typeof y!="object"&&typeof y!="function"&&y!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,y,R,"setState")},Ot.prototype.forceUpdate=function(y){this.updater.enqueueForceUpdate(this,y,"forceUpdate")};function te(){}te.prototype=Ot.prototype;function nt(y,R,F){this.props=y,this.context=R,this.refs=dt,this.updater=F||I}var Xt=nt.prototype=new te;Xt.constructor=nt,V(Xt,Ot.prototype),Xt.isPureReactComponent=!0;var ee=Array.isArray;function ct(){}var yt={H:null,A:null,T:null,S:null},le=Object.prototype.hasOwnProperty;function de(y,R,F){var K=F.ref;return{$$typeof:i,type:y,key:R,ref:K!==void 0?K:null,props:F}}function Kt(y,R){return de(y.type,R,y.props)}function Ft(y){return typeof y=="object"&&y!==null&&y.$$typeof===i}function Wt(y){var R={"=":"=0",":":"=2"};return"$"+y.replace(/[=:]/g,function(F){return R[F]})}var tl=/\/+/g;function mt(y,R){return typeof y=="object"&&y!==null&&y.key!=null?Wt(""+y.key):R.toString(36)}function Y(y){switch(y.status){case"fulfilled":return y.value;case"rejected":throw y.reason;default:switch(typeof y.status=="string"?y.then(ct,ct):(y.status="pending",y.then(function(R){y.status==="pending"&&(y.status="fulfilled",y.value=R)},function(R){y.status==="pending"&&(y.status="rejected",y.reason=R)})),y.status){case"fulfilled":return y.value;case"rejected":throw y.reason}}throw y}function A(y,R,F,K,pt){var ht=typeof y;(ht==="undefined"||ht==="boolean")&&(y=null);var _t=!1;if(y===null)_t=!0;else switch(ht){case"bigint":case"string":case"number":_t=!0;break;case"object":switch(y.$$typeof){case i:case r:_t=!0;break;case Q:return _t=y._init,A(_t(y._payload),R,F,K,pt)}}if(_t)return pt=pt(y),_t=K===""?"."+mt(y,0):K,ee(pt)?(F="",_t!=null&&(F=_t.replace(tl,"$&/")+"/"),A(pt,R,F,"",function(ge){return ge})):pt!=null&&(Ft(pt)&&(pt=Kt(pt,F+(pt.key==null||y&&y.key===pt.key?"":(""+pt.key).replace(tl,"$&/")+"/")+_t)),R.push(pt)),1;_t=0;var k=K===""?".":K+":";if(ee(y))for(var ut=0;ut>>1,gt=Y[Tt];if(0<_(gt,A))Y[Tt]=A,Y[et]=gt,et=Tt;else break t}}function m(Y){return Y.length===0?null:Y[0]}function o(Y){if(Y.length===0)return null;var A=Y[0],et=Y.pop();if(et!==A){Y[0]=et;t:for(var Tt=0,gt=Y.length,ie=gt>>>1;Tt_(ze,et))y_(R,ze)?(Y[Tt]=R,Y[y]=et,Tt=y):(Y[Tt]=ze,Y[Oe]=et,Tt=Oe);else if(y_(R,et))Y[Tt]=R,Y[y]=et,Tt=y;else break t}}return A}function _(Y,A){var et=Y.sortIndex-A.sortIndex;return et!==0?et:Y.id-A.id}if(i.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var C=performance;i.unstable_now=function(){return C.now()}}else{var N=Date,x=N.now();i.unstable_now=function(){return N.now()-x}}var G=[],U=[],Q=1,b=null,B=3,lt=!1,at=!1,I=!1,V=!1,dt=typeof setTimeout=="function"?setTimeout:null,Ot=typeof clearTimeout=="function"?clearTimeout:null,te=typeof setImmediate<"u"?setImmediate:null;function nt(Y){for(var A=m(U);A!==null;){if(A.callback===null)o(U);else if(A.startTime<=Y)o(U),A.sortIndex=A.expirationTime,r(G,A);else break;A=m(U)}}function Xt(Y){if(I=!1,nt(Y),!at)if(m(G)!==null)at=!0,ee||(ee=!0,Ft());else{var A=m(U);A!==null&&mt(Xt,A.startTime-Y)}}var ee=!1,ct=-1,yt=5,le=-1;function de(){return V?!0:!(i.unstable_now()-leY&&de());){var Tt=b.callback;if(typeof Tt=="function"){b.callback=null,B=b.priorityLevel;var gt=Tt(b.expirationTime<=Y);if(Y=i.unstable_now(),typeof gt=="function"){b.callback=gt,nt(Y),A=!0;break e}b===m(G)&&o(G),nt(Y)}else o(G);b=m(G)}if(b!==null)A=!0;else{var ie=m(U);ie!==null&&mt(Xt,ie.startTime-Y),A=!1}}break t}finally{b=null,B=et,lt=!1}A=void 0}}finally{A?Ft():ee=!1}}}var Ft;if(typeof te=="function")Ft=function(){te(Kt)};else if(typeof MessageChannel<"u"){var Wt=new MessageChannel,tl=Wt.port2;Wt.port1.onmessage=Kt,Ft=function(){tl.postMessage(null)}}else Ft=function(){dt(Kt,0)};function mt(Y,A){ct=dt(function(){Y(i.unstable_now())},A)}i.unstable_IdlePriority=5,i.unstable_ImmediatePriority=1,i.unstable_LowPriority=4,i.unstable_NormalPriority=3,i.unstable_Profiling=null,i.unstable_UserBlockingPriority=2,i.unstable_cancelCallback=function(Y){Y.callback=null},i.unstable_forceFrameRate=function(Y){0>Y||125Tt?(Y.sortIndex=et,r(U,Y),m(G)===null&&Y===m(U)&&(I?(Ot(ct),ct=-1):I=!0,mt(Xt,et-Tt))):(Y.sortIndex=gt,r(G,Y),at||lt||(at=!0,ee||(ee=!0,Ft()))),Y},i.unstable_shouldYield=de,i.unstable_wrapCallback=function(Y){var A=B;return function(){var et=B;B=A;try{return Y.apply(this,arguments)}finally{B=et}}}})(cr)),cr}var Dh;function Dy(){return Dh||(Dh=1,ir.exports=Ry()),ir.exports}var sr={exports:{}},Ae={};/** + */var Rh;function Hy(){return Rh||(Rh=1,(function(i){function r(Y,A){var et=Y.length;Y.push(A);t:for(;0>>1,gt=Y[Tt];if(0<_(gt,A))Y[Tt]=A,Y[et]=gt,et=Tt;else break t}}function m(Y){return Y.length===0?null:Y[0]}function o(Y){if(Y.length===0)return null;var A=Y[0],et=Y.pop();if(et!==A){Y[0]=et;t:for(var Tt=0,gt=Y.length,ie=gt>>>1;Tt_(ze,et))y_(R,ze)?(Y[Tt]=R,Y[y]=et,Tt=y):(Y[Tt]=ze,Y[Oe]=et,Tt=Oe);else if(y_(R,et))Y[Tt]=R,Y[y]=et,Tt=y;else break t}}return A}function _(Y,A){var et=Y.sortIndex-A.sortIndex;return et!==0?et:Y.id-A.id}if(i.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var C=performance;i.unstable_now=function(){return C.now()}}else{var N=Date,x=N.now();i.unstable_now=function(){return N.now()-x}}var G=[],U=[],Q=1,b=null,B=3,lt=!1,at=!1,I=!1,V=!1,dt=typeof setTimeout=="function"?setTimeout:null,Ot=typeof clearTimeout=="function"?clearTimeout:null,te=typeof setImmediate<"u"?setImmediate:null;function nt(Y){for(var A=m(U);A!==null;){if(A.callback===null)o(U);else if(A.startTime<=Y)o(U),A.sortIndex=A.expirationTime,r(G,A);else break;A=m(U)}}function Xt(Y){if(I=!1,nt(Y),!at)if(m(G)!==null)at=!0,ee||(ee=!0,Ft());else{var A=m(U);A!==null&&mt(Xt,A.startTime-Y)}}var ee=!1,ct=-1,yt=5,le=-1;function de(){return V?!0:!(i.unstable_now()-leY&&de());){var Tt=b.callback;if(typeof Tt=="function"){b.callback=null,B=b.priorityLevel;var gt=Tt(b.expirationTime<=Y);if(Y=i.unstable_now(),typeof gt=="function"){b.callback=gt,nt(Y),A=!0;break e}b===m(G)&&o(G),nt(Y)}else o(G);b=m(G)}if(b!==null)A=!0;else{var ie=m(U);ie!==null&&mt(Xt,ie.startTime-Y),A=!1}}break t}finally{b=null,B=et,lt=!1}A=void 0}}finally{A?Ft():ee=!1}}}var Ft;if(typeof te=="function")Ft=function(){te(Kt)};else if(typeof MessageChannel<"u"){var Wt=new MessageChannel,tl=Wt.port2;Wt.port1.onmessage=Kt,Ft=function(){tl.postMessage(null)}}else Ft=function(){dt(Kt,0)};function mt(Y,A){ct=dt(function(){Y(i.unstable_now())},A)}i.unstable_IdlePriority=5,i.unstable_ImmediatePriority=1,i.unstable_LowPriority=4,i.unstable_NormalPriority=3,i.unstable_Profiling=null,i.unstable_UserBlockingPriority=2,i.unstable_cancelCallback=function(Y){Y.callback=null},i.unstable_forceFrameRate=function(Y){0>Y||125Tt?(Y.sortIndex=et,r(U,Y),m(G)===null&&Y===m(U)&&(I?(Ot(ct),ct=-1):I=!0,mt(Xt,et-Tt))):(Y.sortIndex=gt,r(G,Y),at||lt||(at=!0,ee||(ee=!0,Ft()))),Y},i.unstable_shouldYield=de,i.unstable_wrapCallback=function(Y){var A=B;return function(){var et=B;B=A;try{return Y.apply(this,arguments)}finally{B=et}}}})(cr)),cr}var Dh;function By(){return Dh||(Dh=1,ir.exports=Hy()),ir.exports}var sr={exports:{}},Ae={};/** * @license React * react-dom.production.js * @@ -36,7 +36,7 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var Uh;function Uy(){if(Uh)return Ae;Uh=1;var i=dr();function r(Q){var b="https://react.dev/errors/"+Q;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(r){console.error(r)}}return i(),sr.exports=Uy(),sr.exports}/** + */var Uh;function qy(){if(Uh)return Ae;Uh=1;var i=dr();function r(Q){var b="https://react.dev/errors/"+Q;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(r){console.error(r)}}return i(),sr.exports=qy(),sr.exports}/** * @license React * react-dom-client.production.js * @@ -44,19 +44,19 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var Bh;function By(){if(Bh)return ui;Bh=1;var i=Dy(),r=dr(),m=Hy();function o(t){var e="https://react.dev/errors/"+t;if(1Ul||(t.current=Va[Ul],Va[Ul]=null,Ul--)}function zt(t,e){Ul++,Va[Ul]=t.current,t.current=e}var Re=Le(null),Fl=Le(null),ae=Le(null),ha=Le(null);function El(t,e){switch(zt(ae,e),zt(Fl,t),zt(Re,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?qm(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=qm(e),t=Ym(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}Gt(Re),zt(Re,t)}function el(){Gt(Re),Gt(Fl),Gt(ae)}function Ze(t){var e=t.memoizedState;e!==null&&(nu._currentValue=e.memoizedState,zt(ha,t)),e=Re.current;var l=Ym(e,t.type);e!==l&&(zt(Fl,t),zt(Re,l))}function ne(t){Fl.current===t&&(Gt(Re),Gt(Fl)),ha.current===t&&(Gt(ha),nu._currentValue=ge)}var qe,ol;function pe(t){if(qe===void 0)try{throw Error()}catch(l){var e=l.stack.trim().match(/\n( *(at )?)/);qe=e&&e[1]||"",ol=-1Ul||(t.current=Va[Ul],Va[Ul]=null,Ul--)}function zt(t,e){Ul++,Va[Ul]=t.current,t.current=e}var Re=Le(null),Fl=Le(null),ae=Le(null),ha=Le(null);function El(t,e){switch(zt(ae,e),zt(Fl,t),zt(Re,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?qm(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=qm(e),t=Ym(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}Gt(Re),zt(Re,t)}function el(){Gt(Re),Gt(Fl),Gt(ae)}function Ze(t){var e=t.memoizedState;e!==null&&(nu._currentValue=e.memoizedState,zt(ha,t)),e=Re.current;var l=Ym(e,t.type);e!==l&&(zt(Fl,t),zt(Re,l))}function ne(t){Fl.current===t&&(Gt(Re),Gt(Fl)),ha.current===t&&(Gt(ha),nu._currentValue=ge)}var qe,ol;function pe(t){if(qe===void 0)try{throw Error()}catch(l){var e=l.stack.trim().match(/\n( *(at )?)/);qe=e&&e[1]||"",ol=-1)":-1n||d[a]!==S[n]){var E=` `+d[a].replace(" at new "," at ");return t.displayName&&E.includes("")&&(E=E.replace("",t.displayName)),E}while(1<=a&&0<=n);break}}}finally{Hl=!1,Error.prepareStackTrace=l}return(l=t?t.displayName||t.name:"")?pe(l):""}function Bl(t,e){switch(t.tag){case 26:case 27:case 5:return pe(t.type);case 16:return pe("Lazy");case 13:return t.child!==e&&e!==null?pe("Suspense Fallback"):pe("Suspense");case 19:return pe("SuspenseList");case 0:case 15:return dl(t.type,!1);case 11:return dl(t.type.render,!1);case 1:return dl(t.type,!0);case 31:return pe("Activity");case 30:return pe("ViewTransition");default:return""}}function Ye(t){try{var e="",l=null;do e+=Bl(t,l),l=t,t=t.return;while(t);return e}catch(a){return` Error generating stack: `+a.message+` -`+a.stack}}var Vt=Object.prototype.hasOwnProperty,ll=i.unstable_scheduleCallback,ml=i.unstable_cancelCallback,ql=i.unstable_shouldYield,La=i.unstable_requestPaint,$t=i.unstable_now,Wl=i.unstable_getCurrentPriorityLevel,yn=i.unstable_ImmediatePriority,gn=i.unstable_UserBlockingPriority,Ke=i.unstable_NormalPriority,Za=i.unstable_LowPriority,va=i.unstable_IdlePriority,ou=i.log,du=i.unstable_setDisableYieldValue,$l=null,Se=null;function hl(t){if(typeof ou=="function"&&du(t),Se&&typeof Se.setStrictMode=="function")try{Se.setStrictMode($l,t)}catch{}}var be=Math.clz32?Math.clz32:L,H=Math.log,D=Math.LN2;function L(t){return t>>>=0,t===0?32:31-(H(t)/D|0)|0}var J=256,Ct=262144,Nl=4194304;function De(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&-t;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function z(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var n=0,u=t.suspendedLanes,c=t.pingedLanes;t=t.warmLanes;var f=a&134217727;return f!==0?(a=f&~u,a!==0?n=De(a):(c&=f,c!==0?n=De(c):l||(l=f&~t,l!==0&&(n=De(l))))):(f=a&~u,f!==0?n=De(f):c!==0?n=De(c):l||(l=a&~t,l!==0&&(n=De(l)))),n===0?0:e!==0&&e!==n&&(e&u)===0&&(u=n&-n,l=e&-e,u>=l||u===32&&(l&4194048)!==0)?e:n}function w(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function W(t,e){(e&8)!==0&&(e|=e&32);var l=t.entangledLanes;if(l!==0)for(t=t.entanglements,l&=e;0l;l++)e.push(t);return e}function Ue(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function ya(t,e,l,a,n,u){var c=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var f=t.entanglements,d=t.expirationTimes,S=t.hiddenUpdates;for(l=c&~l;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),wc=!1;if(ea)try{var gu={};Object.defineProperty(gu,"passive",{get:function(){wc=!0}}),window.addEventListener("test",gu,gu),window.removeEventListener("test",gu,gu)}catch{wc=!1}var ga=null,Gc=null,mi=null;function Rr(){if(mi)return mi;var t,e=Gc,l=e.length,a,n="value"in ga?ga.value:ga.textContent,u=n.length;for(t=0;t=bu),Yr=" ",wr=!1;function Gr(t,e){switch(t){case"keyup":return Ev.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Qr(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Nn=!1;function Cv(t,e){switch(t){case"compositionend":return Qr(e);case"keypress":return e.which!==32?null:(wr=!0,Yr);case"textInput":return t=e.data,t===Yr&&wr?null:t;default:return null}}function Av(t,e){if(Nn)return t==="compositionend"||!Lc&&Gr(t,e)?(t=Rr(),mi=Gc=ga=null,Nn=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1"u")return null;try{return t.activeElement||t.body}catch{return t.body}}function Fr(t){for(;t&&t.firstChild;)t=t.firstChild;return t}function Wr(t,e){var l=Fr(t);t=0;for(var a;l;){if(l.nodeType===3){if(a=t+l.textContent.length,t<=e&&a>=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=Fr(l)}}function $r(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?$r(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function Ir(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=Jc(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=Jc(t.document)}return e}function Fc(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var Bv=ea&&"documentMode"in document&&11>=document.documentMode,Cn=null,Wc=null,_u=null,$c=!1;function Pr(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;$c||Cn==null||Cn!==Jc(a)||(a=Cn,"selectionStart"in a&&Fc(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),_u&&Tu(_u,a)||(_u=a,a=pc(Wc,"onSelect"),0>=c,n-=c,wl=1<<32-be(e)+n|l<it?(re=P,P=null):re=P.sibling;var Et=g(p,P,j[it],M);if(Et===null){P===null&&(P=re);break}t&&P&&Et.alternate===null&&e(p,P),h=u(Et,h,it),xt===null?X=Et:xt.sibling=Et,xt=Et,P=re}if(it===j.length)return l(p,P),vt&&ua(p,it),X;if(P===null){for(;itit?(re=P,P=null):re=P.sibling;var ka=g(p,P,Et.value,M);if(ka===null){P===null&&(P=re);break}t&&P&&ka.alternate===null&&e(p,P),h=u(ka,h,it),xt===null?X=ka:xt.sibling=ka,xt=ka,P=re}if(Et.done)return l(p,P),vt&&ua(p,it),X;if(P===null){for(;!Et.done;it++,Et=j.next())Et=O(p,Et.value,M),Et!==null&&(h=u(Et,h,it),xt===null?X=Et:xt.sibling=Et,xt=Et);return vt&&ua(p,it),X}for(P=a(P);!Et.done;it++,Et=j.next())Et=T(P,p,it,Et.value,M),Et!==null&&(t&&(re=Et.alternate,re!==null&&P.delete(re.key===null?it:re.key)),h=u(Et,h,it),xt===null?X=Et:xt.sibling=Et,xt=Et);return t&&P.forEach(function(Cy){return e(p,Cy)}),vt&&ua(p,it),X}function rt(p,h,j,M){if(typeof j=="object"&&j!==null&&j.type===Kt&&j.key===null&&j.props.ref===void 0&&(j=j.props.children),typeof j=="object"&&j!==null){switch(j.$$typeof){case le:t:{for(var X=j.key;h!==null;){if(h.key===X){if(X=j.type,X===Kt){if(h.tag===7){l(p,h.sibling),M=n(h,j.props.children),Ta(M,j),M.return=p,p=M;break t}}else if(h.elementType===X||typeof X=="object"&&X!==null&&X.$$typeof===gt&&un(X)===h.type){l(p,h.sibling),M=n(h,j.props),Ta(M,j),M.return=p,p=M;break t}l(p,h);break}else e(p,h);h=h.sibling}j.type===Kt?(M=Ia(j.props.children,p.mode,M,j.key),Ta(M,j),M.return=p,p=M):(M=Ti(j.type,j.key,j.props,null,p.mode,M),Ta(M,j),M.return=p,p=M)}return c(p);case de:t:{for(X=j.key;h!==null;){if(h.key===X)if(h.tag===4&&h.stateNode.containerInfo===j.containerInfo&&h.stateNode.implementation===j.implementation){l(p,h.sibling),M=n(h,j.children||[]),M.return=p,p=M;break t}else{l(p,h);break}else e(p,h);h=h.sibling}M=ns(j,p.mode,M),M.return=p,p=M}return c(p);case gt:return j=un(j),rt(p,h,j,M)}if(_t(j))return q(p,h,j,M);if(K(j)){if(X=K(j),typeof X!="function")throw Error(o(150));return j=X.call(j),Z(p,h,j,M)}if(typeof j.then=="function")return rt(p,h,Di(j),M);if(j.$$typeof===mt)return rt(p,h,Mi(p,j),M);Ui(p,j)}return typeof j=="string"&&j!==""||typeof j=="number"||typeof j=="bigint"?(j=""+j,h!==null&&h.tag===6?(l(p,h.sibling),M=n(h,j),M.return=p,p=M):(l(p,h),M=as(j,p.mode,M),M.return=p,p=M),c(p)):l(p,h)}return function(p,h,j,M){try{Ou=0;var X=rt(p,h,j,M);return Bn=null,X}catch(P){if(P===Hn||P===zi)throw P;var xt=Fe(29,P,null,p.mode);return xt.lanes=M,xt.return=p,xt}finally{}}}var sn=_o(!0),Eo=_o(!1),_a=!1;function hs(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function vs(t,e){t=t.updateQueue,e.updateQueue===t&&(e.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Ea(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Na(t,e,l){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(At&2)!==0){var n=a.pending;return n===null?e.next=e:(e.next=n.next,n.next=e),a.pending=e,e=xi(t),co(t,null,l),e}return ji(t,a,e,l),xi(t)}function zu(t,e,l){if(e=e.updateQueue,e!==null&&(e=e.shared,(l&4194048)!==0)){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,ii(t,l)}}function ys(t,e){var l=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var c={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=c:u=u.next=c,l=l.next}while(l!==null);u===null?n=u=e:u=u.next=e}else n=u=e;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},t.updateQueue=l;return}t=l.lastBaseUpdate,t===null?l.firstBaseUpdate=e:t.next=e,l.lastBaseUpdate=e}var gs=!1;function Ru(){if(gs){var t=Un;if(t!==null)throw t}}function Du(t,e,l,a){gs=!1;var n=t.updateQueue;_a=!1;var u=n.firstBaseUpdate,c=n.lastBaseUpdate,f=n.shared.pending;if(f!==null){n.shared.pending=null;var d=f,S=d.next;d.next=null,c===null?u=S:c.next=S,c=d;var E=t.alternate;E!==null&&(E=E.updateQueue,f=E.lastBaseUpdate,f!==c&&(f===null?E.firstBaseUpdate=S:f.next=S,E.lastBaseUpdate=d))}if(u!==null){var O=n.baseState;c=0,E=S=d=null,f=u;do{var g=f.lane&-536870913,T=g!==f.lane;if(T?(jt&g)===g:(a&g)===g){g!==0&&g===an&&(gs=!0),E!==null&&(E=E.next={lane:0,tag:f.tag,payload:f.payload,callback:null,next:null});t:{var q=t,Z=f;g=e;var rt=l;switch(Z.tag){case 1:if(q=Z.payload,typeof q=="function"){O=q.call(rt,O,g);break t}O=q;break t;case 3:q.flags=q.flags&-65537|128;case 0:if(q=Z.payload,g=typeof q=="function"?q.call(rt,O,g):q,g==null)break t;O=ct({},O,g);break t;case 2:_a=!0}}g=f.callback,g!==null&&(t.flags|=64,T&&(t.flags|=8192),T=n.callbacks,T===null?n.callbacks=[g]:T.push(g))}else T={lane:g,tag:f.tag,payload:f.payload,callback:f.callback,next:null},E===null?(S=E=T,d=O):E=E.next=T,c|=g;if(f=f.next,f===null){if(f=n.shared.pending,f===null)break;T=f,f=T.next,T.next=null,n.lastBaseUpdate=T,n.shared.pending=null}}while(!0);E===null&&(d=O),n.baseState=d,n.firstBaseUpdate=S,n.lastBaseUpdate=E,u===null&&(n.shared.lanes=0),Da|=c,t.lanes=c,t.memoizedState=O}}function No(t,e){if(typeof t!="function")throw Error(o(191,t));t.call(e)}function Co(t,e){var l=t.callbacks;if(l!==null)for(t.callbacks=null,t=0;tu?u:8;var c=k.T,f={};f.types=c!==null?c.types:null,k.T=f,qs(t,!1,e,l);try{var d=n(),S=k.S;if(S!==null&&S(f,d),d!==null&&typeof d=="object"&&typeof d.then=="function"){var E=Kv(d,a);qu(t,e,E,fl(t))}else qu(t,e,a,fl(t))}catch(O){qu(t,e,{then:function(){},status:"rejected",reason:O},fl())}finally{ut.p=u,c!==null&&f.types!==null&&(c.types=f.types),k.T=c}}function Pv(){}function Hs(t,e,l,a){if(t.tag!==5)throw Error(o(476));var n=ud(t).queue;nd(t,n,e,ge,l===null?Pv:function(){return id(t),l(a)})}function ud(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:ge,baseState:ge,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:fa,lastRenderedState:ge},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:fa,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function id(t){var e=ud(t);e.next===null&&(e=t.alternate.memoizedState),qu(t,e.next.queue,{},fl())}function Bs(){return Te(nu)}function cd(){return ue().memoizedState}function sd(){return ue().memoizedState}function t0(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=fl();t=Ea(l);var a=Na(e,t,l);a!==null&&(Pe(a,e,l),zu(a,e,l)),e={cache:rs()},t.payload=e;return}e=e.return}}function e0(t,e,l){var a=fl();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Vi(t)?rd(e,l):(l=es(t,e,l,a),l!==null&&(Pe(l,t,a),od(l,e,a)))}function fd(t,e,l){var a=fl();qu(t,e,l,a)}function qu(t,e,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Vi(t))rd(e,n);else{var u=t.alternate;if(t.lanes===0&&(u===null||u.lanes===0)&&(u=e.lastRenderedReducer,u!==null))try{var c=e.lastRenderedState,f=u(c,l);if(n.hasEagerState=!0,n.eagerState=f,nl(f,c))return ji(t,e,n,0),wt===null&&bi(),!1}catch{}finally{}if(l=es(t,e,n,a),l!==null)return Pe(l,t,a),od(l,e,a),!0}return!1}function qs(t,e,l,a){if(a={lane:2,revertLane:Af(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Vi(t)){if(e)throw Error(o(479))}else e=es(t,l,a,2),e!==null&&Pe(e,t,2)}function Vi(t){var e=t.alternate;return t===ft||e!==null&&e===ft}function rd(t,e){qn=qi=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function od(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,ii(t,l)}}var Li={readContext:Te,use:Gi,useCallback:It,useContext:It,useEffect:It,useImperativeHandle:It,useLayoutEffect:It,useInsertionEffect:It,useMemo:It,useReducer:It,useRef:It,useState:It,useDebugValue:It,useDeferredValue:It,useTransition:It,useSyncExternalStore:It,useId:It,useHostTransitionStatus:It,useFormState:It,useActionState:It,useOptimistic:It,useMemoCache:It,useCacheRefresh:It,useEffectEvent:It},dd={readContext:Te,use:Gi,useCallback:function(t,e){return Qe().memoizedState=[t,e===void 0?null:e],t},useContext:Te,useEffect:Fo,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,ki(4194308,4,Po.bind(null,e,t),l)},useLayoutEffect:function(t,e){return ki(4194308,4,t,e)},useInsertionEffect:function(t,e){ki(4,2,t,e)},useMemo:function(t,e){var l=Qe();e=e===void 0?null:e;var a=t();if(fn){hl(!0);try{t()}finally{hl(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=Qe();if(l!==void 0){var n=l(e);if(fn){hl(!0);try{l(e)}finally{hl(!1)}}}else n=e;return a.memoizedState=a.baseState=n,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:n},a.queue=t,t=t.dispatch=e0.bind(null,ft,t),[a.memoizedState,t]},useRef:function(t){var e=Qe();return t={current:t},e.memoizedState=t},useState:function(t){t=Os(t);var e=t.queue,l=fd.bind(null,ft,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:Ds,useDeferredValue:function(t,e){var l=Qe();return Us(l,t,e)},useTransition:function(){var t=Os(!1);return t=nd.bind(null,ft,t.queue,!0,!1),Qe().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=ft,n=Qe();if(vt){if(l===void 0)throw Error(o(407));l=l()}else{if(l=e(),wt===null)throw Error(o(349));(jt&127)!==0||Do(a,e,l)}n.memoizedState=l;var u={value:l,getSnapshot:e};return n.queue=u,Fo(Ho.bind(null,a,u,t),[t]),a.flags|=2048,wn(9,{destroy:void 0},Uo.bind(null,a,u,l,e),null),l},useId:function(){var t=Qe(),e=wt.identifierPrefix;if(vt){var l=Gl,a=wl;l=(a&~(1<<32-be(a)-1)).toString(32)+l,e="_"+e+"R_"+l,l=Yi++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?c.createElement("select",{is:a.is}):c.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?c.createElement(n,{is:a.is}):c.createElement(n)}}u[xe]=e,u[Je]=a;t:for(c=e.child;c!==null;){if(c.tag===5||c.tag===6)u.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===e)break t;for(;c.sibling===null;){if(c.return===null||c.return===e)break t;c=c.return}c.sibling.return=c.return,c=c.sibling}e.stateNode=u;t:switch(Ce(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&oa(e)}}return kt(e),e.subtreeFlags&=-33554433,Ws(e,e.type,t===null?null:t.memoizedProps,e.pendingProps,l),null;case 6:if(t&&e.stateNode!=null)t.memoizedProps!==a&&oa(e);else{if(typeof a!="string"&&e.stateNode===null)throw Error(o(166));if(t=ae.current,Dn(e)){if(t=e.stateNode,l=e.memoizedProps,a=null,n=he,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}t[xe]=e,t=!!(t.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||Hm(t.nodeValue,l)),t||ja(e,!0)}else t=Wu(t).createTextNode(a),t[xe]=e,e.stateNode=t}return kt(e),null;case 31:if(l=e.memoizedState,t===null||t.memoizedState!==null){if(a=Dn(e),l!==null){if(t===null){if(!a)throw Error(o(318));if(t=e.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(o(557));t[xe]=e}else Pa(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;kt(e),t=!1}else l=cs(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=l),t=!0;if(!t)return e.flags&256?(ul(e),e):(ul(e),null);if((e.flags&128)!==0)throw Error(o(558))}return kt(e),null;case 13:if(a=e.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(n=Dn(e),a!==null&&a.dehydrated!==null){if(t===null){if(!n)throw Error(o(318));if(n=e.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(o(317));n[xe]=e}else Pa(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;kt(e),n=!1}else n=cs(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=n),n=!0;if(!n)return e.flags&256?(ul(e),e):(ul(e),null)}return ul(e),(e.flags&128)!==0?(e.lanes=l,e):(l=a!==null,t=t!==null&&t.memoizedState!==null,l&&(a=e.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==t&&l&&(e.child.flags|=8192),$i(e,e.updateQueue),kt(e),null);case 4:return el(),t===null&&Rf(e.stateNode.containerInfo),e.flags|=67108864,kt(e),null;case 10:return ca(e.type),kt(e),null;case 19:if(js(e),a=e.memoizedState,a===null)return kt(e),null;if(n=(e.flags&128)!==0,u=a.rendering,u===null)if(n)wu(a,!1);else{if(Pt!==0||t!==null&&(t.flags&128)!==0)for(t=e.child;t!==null;){if(u=Bi(t),u!==null){for(e.flags|=128,wu(a,!1),t=u.updateQueue,e.updateQueue=t,$i(e,t),e.subtreeFlags=0,t=l,l=e.child;l!==null;)so(l,t),l=l.sibling;return Uu(e,Ee.current&1|2),vt&&ua(e,a.treeForkCount),e.child}t=t.sibling}a.tail!==null&&$t()>fc&&(e.flags|=128,n=!0,wu(a,!1),e.lanes=4194304)}else{if(!n)if(t=Bi(u),t!==null){if(e.flags|=128,n=!0,t=t.updateQueue,e.updateQueue=t,$i(e,t),wu(a,!0),a.tail===null&&a.tailMode!=="collapsed"&&a.tailMode!=="visible"&&!u.alternate&&!vt)return kt(e),null}else 2*$t()-a.renderingStartTime>fc&&l!==536870912&&(e.flags|=128,n=!0,wu(a,!1),e.lanes=4194304);a.isBackwards?(u.sibling=e.child,e.child=u):(t=a.last,t!==null?t.sibling=u:e.child=u,a.last=u)}if(a.tail!==null){t=a.tail;t:{for(l=t;l!==null;){if(l.alternate!==null){l=!1;break t}l=l.sibling}l=!0}return a.rendering=t,a.tail=t.sibling,a.renderingStartTime=$t(),t.sibling=null,u=Ee.current,u=n?u&1|2:u&1,a.tailMode==="visible"||a.tailMode==="collapsed"||!l||vt?Uu(e,u):(l=u,zt(_e,e),zt(Ee,l),Be===null&&(Be=e)),vt&&ua(e,a.treeForkCount),t}return kt(e),null;case 22:case 23:return ul(e),Ss(),a=e.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(e.flags|=8192):a&&(e.flags|=8192),a?(l&536870912)!==0&&(e.flags&128)===0&&(kt(e),e.subtreeFlags&6&&(e.flags|=8192)):kt(e),l=e.updateQueue,l!==null&&$i(e,l.retryQueue),l=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(l=t.memoizedState.cachePool.pool),a=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),a!==l&&(e.flags|=2048),t!==null&&Gt(nn),null;case 24:return l=null,t!==null&&(l=t.memoizedState.cache),e.memoizedState.cache!==l&&(e.flags|=2048),ca(ce),kt(e),null;case 25:return null;case 30:return e.flags|=33554432,kt(e),null}throw Error(o(156,e.tag))}function s0(t,e){switch(us(e),e.tag){case 1:return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 3:return ca(ce),el(),t=e.flags,(t&65536)!==0&&(t&128)===0?(e.flags=t&-65537|128,e):null;case 26:case 27:case 5:return ne(e),null;case 31:if(e.memoizedState!==null){if(ul(e),e.alternate===null)throw Error(o(340));Pa()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 13:if(ul(e),t=e.memoizedState,t!==null&&t.dehydrated!==null){if(e.alternate===null)throw Error(o(340));Pa()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 19:return js(e),t=e.flags,t&65536?(e.flags=t&-65537|128,t=e.memoizedState,t!==null&&(t.rendering=null,t.tail=null),e.flags|=4,e):null;case 4:return el(),null;case 10:return ca(e.type),null;case 22:case 23:return ul(e),Ss(),t!==null&&Gt(nn),t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 24:return ca(ce),null;case 25:return null;default:return null}}function qd(t,e){switch(us(e),e.tag){case 3:ca(ce),el();break;case 26:case 27:case 5:ne(e);break;case 4:el();break;case 31:e.memoizedState!==null&&ul(e);break;case 13:ul(e);break;case 19:js(e);break;case 10:ca(e.type);break;case 22:case 23:ul(e),Ss(),t!==null&&Gt(nn);break;case 24:ca(ce)}}function Gu(t,e){try{var l=e.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&t)===t){a=void 0;var u=l.create,c=l.inst;a=u(),c.destroy=a}l=l.next}while(l!==n)}}catch(f){Ht(e,e.return,f)}}function Oa(t,e,l){try{var a=e.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&t)===t){var c=a.inst,f=c.destroy;if(f!==void 0){c.destroy=void 0,n=e;var d=l,S=f;try{S()}catch(E){Ht(n,d,E)}}}a=a.next}while(a!==u)}}catch(E){Ht(e,e.return,E)}}function Yd(t){var e=t.updateQueue;if(e!==null){var l=t.stateNode;try{Co(e,l)}catch(a){Ht(t,t.return,a)}}}function wd(t,e,l){l.props=rn(t.type,t.memoizedProps),l.state=t.memoizedState;try{l.componentWillUnmount()}catch(a){Ht(t,e,a)}}function Ql(t,e){try{var l=t.ref;if(l!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:var n=t.stateNode,u=la(t.memoizedProps,n);(n.ref===null||n.ref.name!==u)&&(n.ref=Zm(u)),a=n.ref;break;case 7:if(t.stateNode===null){var c=new rl(t);b(t.child,!1,I0,c,void 0,void 0),t.stateNode=c}a=t.stateNode;break;default:a=t.stateNode}typeof l=="function"?t.refCleanup=l(a):l.current=a}}catch(f){Ht(t,e,f)}}function Ne(t,e){var l=t.ref,a=t.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Ht(t,e,n)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){Ht(t,e,n)}else l.current=null}function Ii(t,e){if((t.tag===5||t.tag===27||t.tag===6)&&t.alternate===null&&e!==null)for(var l=0;l title"))),Ce(a,e,l),a[xe]=t,me(a),e=a;break t;case"link":if(u=fh("link","href",n).get(e+(l.href||""))){for(c=0;crt&&(c=rt,rt=Z,Z=c);var p=Wr(f,Z),h=Wr(f,rt);if(p&&h&&(T.rangeCount!==1||T.anchorNode!==p.node||T.anchorOffset!==p.offset||T.focusNode!==h.node||T.focusOffset!==h.offset)){var j=O.createRange();j.setStart(p.node,p.offset),T.removeAllRanges(),Z>rt?(T.addRange(j),T.extend(h.node,h.offset)):(j.setEnd(h.node,h.offset),T.addRange(j))}}}}for(O=[],T=f;T=T.parentNode;)T.nodeType===1&&O.push({element:T,left:T.scrollLeft,top:T.scrollTop});for(typeof f.focus=="function"&&f.focus(),f=0;fl?32:l,k.T=null,l=pf,pf=null;var u=zl,c=Kl;if(Jt=0,hn=zl=null,Kl=0,(At&6)!==0)throw Error(o(331));var f=At;if(At|=4,sm(u.current),um(u,u.current,c,l),At=f,Ku(0,!1),Se&&typeof Se.onPostCommitFiberRoot=="function")try{Se.onPostCommitFiberRoot($l,u)}catch{}return!0}finally{ut.p=n,k.T=a,Tm(t,e)}}function _m(t,e,l){e=gl(l,e),e=Gs(t.stateNode,e,2),t=Na(t,e,2),t!==null&&(Ue(t,2),Jl(t))}function Ht(t,e,l){if(t.tag===3)_m(t,t,l);else for(;e!==null;){if(e.tag===3){_m(e,t,l);break}else if(e.tag===1){var a=e.stateNode;if(typeof e.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Ua===null||!Ua.has(a))){t=gl(l,t),l=bd(2),a=Na(e,l,2),a!==null&&(jd(l,a,e,t),Ue(a,2),Jl(a));break}}e=e.return}}function Ef(t,e,l){var a=t.pingCache;if(a===null){a=t.pingCache=new d0;var n=new Set;a.set(e,n)}else n=a.get(e),n===void 0&&(n=new Set,a.set(e,n));n.has(l)||(vf=!0,n.add(l),t=b0.bind(null,t,e,l),e.then(t,t))}function b0(t,e,l){var a=t.pingCache;a!==null&&a.delete(e),t.pingedLanes|=t.suspendedLanes&l,t.warmLanes&=~l,wt===t&&(jt&l)===l&&((Pt===4||Pt===3&&(jt&62914560)===jt&&300>$t()-sc)&&(At&2)===0?Wn(t,0):cc|=l,Ln===jt&&(Ln=0)),Jl(t)}function Em(t,e){e===0&&(e=Lt()),t=$a(t,e),t!==null&&(Ue(t,e),Jl(t))}function j0(t){var e=t.memoizedState,l=0;e!==null&&(l=e.retryLane),Em(t,l)}function x0(t,e){var l=0;switch(t.tag){case 31:case 13:var a=t.stateNode,n=t.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(o(314))}a!==null&&a.delete(e),Em(t,l)}function T0(t,e){return ll(t,e)}var In=null,Pn=null,Nf=!1,yc=!1,Cf=!1,Ba=0;function Jl(t){t!==Pn&&t.next===null&&(Pn===null?In=Pn=t:Pn=Pn.next=t),yc=!0,Nf||(Nf=!0,E0())}function Ku(t,e){if(!Cf&&yc){Cf=!0;do for(var l=!1,a=In;a!==null;){if(t!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var c=a.suspendedLanes,f=a.pingedLanes;u=(1<<31-be(42|t)+1)-1,u&=n&~(c&~f),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,Mm(a,u))}else u=jt,u=z(a,a===wt?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||w(a,u)||(l=!0,Mm(a,u));a=a.next}while(l);Cf=!1}}function _0(){Nm()}function Nm(){yc=Nf=!1;var t=0;Ba!==0&&B0()&&(t=Ba);for(var e=$t(),l=null,a=In;a!==null;){var n=a.next,u=Cm(a,e);u===0?(a.next=null,l===null?In=n:l.next=n,n===null&&(Pn=l)):(l=a,(t!==0||(u&3)!==0)&&(yc=!0)),a=n}Jt!==0&&Jt!==5||Ku(t),Ba!==0&&(Ba=0)}function Cm(t,e){for(var l=t.suspendedLanes,a=t.pingedLanes,n=t.expirationTimes,u=t.pendingLanes&-62914561;0f)break;var E=d.transferSize,O=d.initiatorType;E&&Bm(O)&&(d=d.responseEnd,c+=E*(djc){Z.length=q;break}j=new Promise(k0.bind(j)),Z.push(j)}}}if(0"u"?null:document;function uh(t,e,l){var a=eu;if(a&&typeof e=="string"&&e){var n=vl(e);n='link[rel="'+t+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),nh.has(n)||(nh.add(n),t={rel:t,crossOrigin:l,href:e},a.querySelector(n)===null&&(e=a.createElement("link"),Ce(e,"link",t),me(e),a.head.appendChild(e)))}}function cy(t){ma.D(t),uh("dns-prefetch",t,null)}function sy(t,e){ma.C(t,e),uh("preconnect",t,e)}function fy(t,e,l){ma.L(t,e,l);var a=eu;if(a&&t&&e){var n='link[rel="preload"][as="'+vl(e)+'"]';e==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+vl(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+vl(l.imageSizes)+'"]')):n+='[href="'+vl(t)+'"]';var u=n;switch(e){case"style":u=lu(t);break;case"script":u=au(t)}if(!(Tl.has(u)||(t=ct({rel:"preload",href:e==="image"&&l&&l.imageSrcSet?void 0:t,as:e},l),Tl.set(u,t),a.querySelector(n)!==null||e==="style"&&a.querySelector(Iu(u))||e==="script"&&a.querySelector(Pu(u))))){var c=a.createElement("link");Ce(c,"link",t),e==="style"&&(c[si]=!0,c.onload=c.onerror=function(){gr(c)}),me(c),a.head.appendChild(c)}}}function ry(t,e){ma.m(t,e);var l=eu;if(l&&t){var a=e&&typeof e.as=="string"?e.as:"script",n='link[rel="modulepreload"][as="'+vl(a)+'"][href="'+vl(t)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=au(t)}if(!Tl.has(u)&&(t=ct({rel:"modulepreload",href:t},e),Tl.set(u,t),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(Pu(u)))return}a=l.createElement("link"),Ce(a,"link",t),me(a),l.head.appendChild(a)}}}function oy(t,e,l){ma.S(t,e,l);var a=eu;if(a&&t){var n=bn(a).hoistableStyles,u=lu(t);e=e||"default";var c=n.get(u);if(!c){var f={loading:0,preload:null};if(c=a.querySelector(Iu(u)))f.loading=5;else{t=ct({rel:"stylesheet",href:t,"data-precedence":e},l),(l=Tl.get(u))&&Jf(t,l);var d=c=a.createElement("link");me(d),Ce(d,"link",t),d._p=new Promise(function(S,E){d.onload=S,d.onerror=E}),d.addEventListener("load",function(){f.loading|=1}),d.addEventListener("error",function(){f.loading|=2}),f.loading|=4,Sc(c,e,a)}c={type:"stylesheet",instance:c,count:1,state:f},n.set(u,c)}}}function dy(t,e){ma.X(t,e);var l=eu;if(l&&t){var a=bn(l).hoistableScripts,n=au(t),u=a.get(n);u||(u=l.querySelector(Pu(n)),u||(t=ct({src:t,async:!0},e),(e=Tl.get(n))&&Ff(t,e),u=l.createElement("script"),me(u),Ce(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function my(t,e){ma.M(t,e);var l=eu;if(l&&t){var a=bn(l).hoistableScripts,n=au(t),u=a.get(n);u||(u=l.querySelector(Pu(n)),u||(t=ct({src:t,async:!0,type:"module"},e),(e=Tl.get(n))&&Ff(t,e),u=l.createElement("script"),me(u),Ce(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function ih(t,e,l,a){var n=(n=ae.current)?$u(n):null;if(!n)throw Error(o(446));switch(t){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(l=lu(l.href),e=bn(n).hoistableStyles,a=e.get(l),a||(a={type:"style",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){t=lu(l.href);var u=bn(n).hoistableStyles,c=u.get(t);if(c||(n=n.ownerDocument||n,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(t,c),(u=n.querySelector(Iu(t)))?u._p||(c.instance=u,c.state.loading=5):(u=Tl.get(t),u||(u={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Tl.set(t,u)),hy(n,t,u,c.state))),e&&a===null)throw Error(o(528,""));return c}if(e&&a!==null)throw Error(o(529,""));return null;case"script":return e=l.async,l=l.src,typeof l=="string"&&e&&typeof e!="function"&&typeof e!="symbol"?(l=au(l),e=bn(n).hoistableScripts,a=e.get(l),a||(a={type:"script",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,t))}}function lu(t){return'href="'+vl(t)+'"'}function Iu(t){return'link[rel="stylesheet"]['+t+"]"}function ch(t){return ct({},t,{"data-precedence":t.precedence,precedence:null})}function hy(t,e,l,a){if(e=t.querySelector('link[rel="preload"][as="style"]['+e+"]")){if(e[si]!==!0){a.loading=1;return}}else e=t.createElement("link"),e[si]=!0,e.onload=e.onerror=gr.bind(null,e),Ce(e,"link",l),me(e),t.head.appendChild(e);a.preload=e,e.addEventListener("load",function(){return a.loading|=1}),e.addEventListener("error",function(){return a.loading|=2})}function au(t){return'[src="'+vl(t)+'"]'}function Pu(t){return"script[async]"+t}function sh(t,e,l){if(e.count++,e.instance===null)switch(e.type){case"style":var a=t.querySelector('style[data-href~="'+vl(l.href)+'"]');if(a)return e.instance=a,me(a),a;var n=ct({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),me(a),Ce(a,"style",n),Sc(a,l.precedence,t),e.instance=a;case"stylesheet":n=lu(l.href);var u=t.querySelector(Iu(n));if(u)return e.state.loading|=4,e.instance=u,me(u),u;a=ch(l),(n=Tl.get(n))&&Jf(a,n),u=(t.ownerDocument||t).createElement("link"),me(u);var c=u;return c._p=new Promise(function(f,d){c.onload=f,c.onerror=d}),Ce(u,"link",a),e.state.loading|=4,Sc(u,l.precedence,t),e.instance=u;case"script":return u=au(l.src),(n=t.querySelector(Pu(u)))?(e.instance=n,me(n),n):(a=l,(n=Tl.get(u))&&(a=ct({},l),Ff(a,n)),t=t.ownerDocument||t,n=t.createElement("script"),me(n),Ce(n,"link",a),t.head.appendChild(n),e.instance=n);case"void":return null;default:throw Error(o(443,e.type))}else e.type==="stylesheet"&&(e.state.loading&4)===0&&(a=e.instance,e.state.loading|=4,Sc(a,l.precedence,t));return e.instance}function Sc(t,e,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,c=0;c title"):null)}function vy(t,e,l){if(l===1||e.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof e.precedence!="string"||typeof e.href!="string"||e.href==="")break;return!0;case"link":if(typeof e.rel!="string"||typeof e.href!="string"||e.href===""||e.onLoad||e.onError)break;switch(e.rel){case"stylesheet":return t=e.disabled,typeof e.precedence=="string"&&t==null;default:return!0}case"script":if(e.async&&typeof e.async!="function"&&typeof e.async!="symbol"&&!e.onLoad&&!e.onError&&e.src&&typeof e.src=="string")return!0}return!1}function rh(t,e){return t==="img"&&e.src!=null&&e.src!==""&&e.onLoad==null&&e.loading!=="lazy"}function oh(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function dh(t){return(t.width||100)*(t.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function mh(t,e){typeof e.decode=="function"&&(t.imgCount++,e.complete||(t.imgBytes+=dh(e),t.suspenseyImages.push(e)),t=py.bind(t),e.decode().then(t,t))}function yy(t,e,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=lu(a.href),u=e.querySelector(Iu(n));if(u){e=u._p,e!==null&&typeof e=="object"&&typeof e.then=="function"&&(t.count++,t=ti.bind(t),e.then(t,t)),l.state.loading|=4,l.instance=u,me(u);return}u=e.ownerDocument||e,a=ch(a),(n=Tl.get(n))&&Jf(a,n),u=u.createElement("link"),me(u);var c=u;c._p=new Promise(function(f,d){c.onload=f,c.onerror=d}),Ce(u,"link",a),l.instance=u}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(l,e),(e=l.state.preload)&&(l.state.loading&3)===0&&(t.count++,l=ti.bind(t),e.addEventListener("load",l),e.addEventListener("error",l))}}var jc=0;function gy(t,e){return t.stylesheets&&t.count===0&&Tc(t,t.stylesheets),0jc?50:800)+e);return t.unsuspend=l,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function hh(t){if(t.count===0&&(t.imgCount===0||!t.waitingForImages)){if(t.stylesheets)Tc(t,t.stylesheets);else if(t.unsuspend){var e=t.unsuspend;t.unsuspend=null,e()}}}function ti(){this.count--,hh(this)}function py(){this.imgCount--,hh(this)}var xc=null;function Tc(t,e){t.stylesheets=null,t.unsuspend!==null&&(t.count++,xc=new Map,e.forEach(Sy,t),xc=null,ti.call(t))}function Sy(t,e){if(!(e.state.loading&4)){var l=xc.get(t);if(l)var a=l.get(null);else{l=new Map,xc.set(t,l);for(var n=t.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(r){console.error(r)}}return i(),ur.exports=By(),ur.exports}var Yy=qy();const wy=wh(Yy),Gh=v.createContext(null);function Mt(){const i=v.useContext(Gh);if(!i)throw new Error("ConsoleContext missing");return i}const ot=encodeURIComponent,$={health:"/health",relayModels:"/relay/models",quotaMe:"/users/me/quota",userKeys:"/users/me/keys",userKey:i=>"/users/me/keys/"+ot(i),githubRepos:"/github/repos",projects:"/projects",project:i=>"/projects/"+ot(i),projectMembers:i=>"/projects/"+ot(i)+"/members",projectMember:(i,r)=>"/projects/"+ot(i)+"/members/"+ot(r),projectSkills:i=>"/projects/"+ot(i)+"/skills",projectApps:i=>"/projects/"+ot(i)+"/apps",projectMcp:i=>"/projects/"+ot(i)+"/mcp-servers",projectMcpReload:i=>"/projects/"+ot(i)+"/mcp-servers/reload",projectMcpOauth:(i,r)=>"/projects/"+ot(i)+"/mcp-servers/"+ot(r)+"/oauth-login",projectAutomations:i=>"/projects/"+ot(i)+"/automations",projectAutomationCancel:(i,r)=>"/projects/"+ot(i)+"/automations/"+ot(r)+"/cancel",projectTriage:i=>"/projects/"+ot(i)+"/triage",workers:"/workers",environments:i=>"/environments?project_id="+ot(i),environmentsCreate:"/environments",environmentArchive:i=>"/environments/"+ot(i)+"/archive",tasks:i=>"/tasks?project_id="+ot(i),tasksByParent:(i,r)=>"/tasks?project_id="+ot(i)+"&parent_task_id="+ot(r),tasksCreate:"/tasks",task:i=>"/tasks/"+ot(i),taskAction:(i,r)=>"/tasks/"+ot(i)+"/"+r,taskFork:i=>"/tasks/"+ot(i)+"/fork",taskContinue:i=>"/tasks/"+ot(i)+"/continue",taskTrace:i=>"/tasks/"+ot(i)+"/trace",taskTraceStream:i=>"/tasks/"+ot(i)+"/trace/stream",taskAgents:i=>"/tasks/"+ot(i)+"/agents",taskReviews:i=>"/tasks/"+ot(i)+"/reviews",taskReviewFindings:(i,r)=>"/tasks/"+ot(i)+"/reviews/"+ot(r)+"/findings",taskApprovals:i=>"/tasks/"+ot(i)+"/approvals",taskApprovalDecision:(i,r,m)=>"/tasks/"+ot(i)+"/approvals/"+ot(r)+"/"+m,taskFollowups:i=>"/tasks/"+ot(i)+"/followups",taskChatHistory:i=>"/tasks/"+ot(i)+"/chat-history",taskMessages:i=>"/tasks/"+ot(i)+"/messages",taskMessagesTo:i=>"/tasks/"+ot(i)+"/messages",taskThread:i=>"/tasks/"+ot(i)+"/thread",taskThreads:i=>"/tasks/"+ot(i)+"/threads",taskThreadAction:(i,r)=>"/tasks/"+ot(i)+"/thread/"+r,taskCost:i=>"/tasks/"+ot(i)+"/cost",uploads:"/uploads",adminQuotas:"/admin/quotas",adminQuotaUser:i=>"/admin/quotas?user_id="+ot(i),adminSweep:"/admin/sweep",adminBackup:"/admin/backup"},Gy={exec:"命令",file:"文件",call:"调用",tool:"工具",message:"消息",reasoning:"思考",plan:"计划","agent-start":"子代理","agent-done":"子代理"},su=["completed","failed","interrupted","merged","merge-failed"],Qy={queued:"排队中,尚未被 worker 认领",running:"运行中,模型回合进行中",completed:"模型回合结束、改动在 worktree 里尚未合并",failed:"模型回合失败,可重试",interrupted:"已被取消/中断,可重试",merged:"控制面已标记 merged,不代表 git 主分支已合入","merge-failed":"合并落盘失败,可重试"},Yh=["low","medium","high","xhigh","max"],ky=["viewer","contributor","maintainer","owner"],mr="codex-console-key";function _l(){try{return localStorage.getItem(mr)||""}catch{return""}}function Xy(i){localStorage.setItem(mr,i)}function Vy(){localStorage.removeItem(mr)}function Me(i){return i?i.slice(0,8):""}function Xa(i){return i?new Date(i*1e3).toLocaleString():""}async function tt(i,r="GET",m){const o={"Content-Type":"application/json"},_=_l();_&&(o["X-API-Key"]=_);const C={method:r,headers:o};m!==void 0&&(C.body=JSON.stringify(m));const N=await fetch(i,C);let x=null;try{x=await N.json()}catch{x=null}if(!N.ok){const G=x;let U=G&&G.error?G.error:"HTTP "+N.status;throw N.status===401&&(U+="(key 未填或无效)"),N.status===429&&(U+="(触发限流,稍后再试)"),N.status===402&&(G&&G.unpriced_token_cap!==void 0?U+="(无价 token 已满,联系管理员调整)":G&&G.error==="coordinator_quota_reserve_exceeded"?U="协调员分工预留不足:剩余美元配额不够覆盖全部分工,子任务费用记父任务创建人账,整个父任务已被挡下(未建任何子任务)":U+="(美元配额已满,联系管理员调整)"),new Error(U)}return x}async function Ly(i){const r=new FormData;r.append("paths",JSON.stringify(i.map(_=>_.path))),i.forEach((_,C)=>r.append("file"+C,_.file));const m=await fetch($.uploads,{method:"POST",headers:{"X-API-Key":_l()},body:r}),o=await m.json().catch(()=>({}));if(!m.ok)throw new Error(o&&o.error||"HTTP "+m.status);return o.upload_id}function Zy(i,r,m){const o=[],_={},C=(N,x)=>{if(N)for(let G=0;GN.name),C(r,N=>N.webkitRelativePath||N.name),C(m,N=>N.name),o}function Qh(i){const r=Date.now()/1e3;let m=null;if(typeof i.last_seen=="number"?m=r-i.last_seen:typeof i.last_seen_seconds_ago=="number"&&(m=i.last_seen_seconds_ago),(m===null||m<0)&&(m=null),m===null)return{text:"未知",age:null};const o=Math.floor(m);return o<60?{text:o+" 秒前",age:m}:o<3600?{text:Math.floor(o/60)+" 分钟前",age:m}:{text:Math.floor(o/3600)+" 小时前",age:m}}function Oc(i){const r=i.message||"";return r.includes("forbidden")?"没有权限:只有项目 owner 或全局管理员可以管理成员":r.includes("already_member")?"该用户已是成员,改角色请用成员行的下拉框":r.includes("cannot demote the only owner")?"不能把唯一 owner 降为非 owner:请先把另一位成员升为 owner":r.includes("user not found")?"找不到该用户:请核对 user_id 或用户名是否正确":r.includes("member not found")?"该用户不是本项目成员":r.includes("unknown role")?"角色无效:只能是 viewer / contributor / maintainer / owner":r.includes("project not found")?"项目不存在(可能已被删除)":"成员操作失败:"+r}function fr(i){const r=i.message||"";return r.includes("forbidden")?"无全局管理员权限:服务端返回 403(CODEX_GLOBAL_ADMINS 未包含当前用户),请联系管理员":r.includes("user not found")?"找不到该用户:请核对用户 id 是否正确":"管理操作失败:"+r}function rr(i){return i==null?"不限额":"$"+(i/1e6).toFixed(2)}function or(i){const r=Gy[i.kind||""]||i.kind||"?";let m="";return i.kind==="exec"?m=(i.command||"")+"(exit="+(i.exitCode??"")+","+(i.durationMs??"")+"ms,cwd="+(i.cwd||"")+")":i.kind==="file"?m=(i.path||"")+" "+(i.change||"")+" "+(i.status||""):i.kind==="message"?m=(i.phase?"["+i.phase+"] ":"")+(i.text||""):i.kind==="reasoning"?m=i.summary||"":i.kind==="tool"?m=(i.server||"")+"/"+(i.tool||"")+" "+(i.status||""):i.kind==="call"?m=i.name||"":i.kind==="plan"?m=i.text||"":i.kind==="agent-start"?m="开始:"+(i.name||"")+(i.prompt?"("+i.prompt+")":""):i.kind==="agent-done"?m="结束:"+(i.name||"")+" "+(i.status||""):m=JSON.stringify(i).slice(0,300),"["+r+"] "+m}function Ky(){const[i,r]=v.useState(!!_l()),[m,o]=v.useState(_l()?"已保存到本浏览器(只用于调本站 API)":"未填 key,数据接口会返回 401"),[_,C]=v.useState("未加载"),[N,x]=v.useState("未加载"),[G,U]=v.useState("填 key 后判断权限…"),[Q,b]=v.useState(!1),[B,lt]=v.useState(""),[at,I]=v.useState(""),[V,dt]=v.useState([]),[Ot,te]=v.useState(""),[nt,Xt]=v.useState(""),[ee,ct]=v.useState([]),[yt,le]=v.useState(null),[de,Kt]=v.useState("未加载"),[Ft,Wt]=v.useState(""),[tl,mt]=v.useState([]),[Y,A]=v.useState(""),[et,Tt]=v.useState(""),[gt,ie]=v.useState([]),[Oe,ze]=v.useState([]),[y,R]=v.useState([]),[F,K]=v.useState("先选项目"),[pt,ht]=v.useState(""),[_t,k]=v.useState(""),[ut,ge]=v.useState(""),[Va,Ul]=v.useState(""),[Le,Gt]=v.useState([]),[zt,Re]=v.useState(""),[Fl,ae]=v.useState(""),[ha,El]=v.useState(""),[el,Ze]=v.useState(!1),[ne,qe]=v.useState(""),[ol,pe]=v.useState(""),[Hl,dl]=v.useState([]),[Bl,Ye]=v.useState(!1),Vt=v.useRef("");Vt.current=Ot;const ll=v.useRef("");ll.current=ol;const ml=v.useCallback(async()=>{try{const z=await tt($.health);x("backend="+z.backend+" db_ok="+z.db_ok+" worker_ok="+z.worker_ok+" commit="+String(z.commit||"").slice(0,7))}catch(z){x("加载失败:"+z.message)}},[]),ql=v.useCallback(async()=>{if(!_l()){C("未填 key,配额不显示");return}try{const z=await tt($.quotaMe),w=((z.used_usd_micros||0)/1e6).toFixed(2),W=z.quota_usd_micros===null||z.quota_usd_micros===void 0?"美元:本月用量 $"+w+"(不限额)":"美元:本月用量 $"+w+" / $"+((z.quota_usd_micros||0)/1e6).toFixed(2)+"(剩余 $"+((z.remaining_usd_micros||0)/1e6).toFixed(2)+")",qt=z.unpriced_token_cap===void 0||z.unpriced_tokens_used===void 0?"无价 token:未返回(旧服务端)":"无价 token:"+z.unpriced_tokens_used+" / "+z.unpriced_token_cap+" tokens";C(W+" | "+qt)}catch(z){C("配额加载失败:"+z.message)}},[]),La=v.useCallback(async()=>{if(!_l()){U("未填 key,管理区不可用"),b(!1);return}try{const z=await fetch($.adminQuotas,{headers:{"X-API-Key":_l()}});z.status===400?(U("已确认为全局管理员,管理操作可用"),b(!0)):z.status===403?(U("管理区仅全局管理员可用:当前 key 无全局管理员权限(服务端返回 403)"),b(!1)):z.status===401?(U("key 无效,管理区不可用(服务端返回 401)"),b(!1)):(U("管理权限判断失败(HTTP "+z.status+"),管理操作暂不可用"),b(!1))}catch(z){U("管理权限判断失败:"+z.message),b(!1)}},[]),$t=v.useCallback(async()=>{try{const w=(await tt($.projects)).projects||[];dt(w),Xt(w.length+" 个项目"),Vt.current&&w.some(W=>W.id===Vt.current)}catch(z){Xt("加载失败:"+z.message)}},[]),Wl=v.useCallback(async()=>{try{const z=await tt($.githubRepos);ct(z.repos||[])}catch{}},[]),yn=v.useCallback(async()=>{try{const z=await tt($.relayModels);dl(z.models||[]),Ye(!1)}catch{Ye(!0)}},[]),gn=v.useCallback(async()=>{try{const z=await tt($.workers);if(!Array.isArray(z)&&z.workers===void 0&&z.workers_total!==void 0){le(null),Kt(z.workers_total?"在线 "+z.workers_online+" / 离线 "+z.workers_offline+"(共 "+z.workers_total+";完整 worker 清单仅全局管理员可见)":"无 worker 注册"),Wt("");return}const w=Array.isArray(z)?z:z.workers||[];le(w),Kt(w.length?"":"无 worker 注册"),Wt("")}catch(z){Wt("加载失败:"+z.message)}},[]),Ke=v.useCallback(async z=>{const w=z!==void 0?z:Vt.current,W=ll.current;if(!w){Gt([]),Re(""),pe("");return}try{const Lt=(await tt($.environments(w))).environments||[];Gt(Lt),Re(Lt.length+" 个环境"),(W&&Lt.some(Ue=>Ue.id===W&&Ue.status==="ready")||W&&Lt.some(Ue=>Ue.id===W))&&pe(W);const je=V.find(Ue=>Ue.id===w);je&&je.repo_url?(El("仓库:"+je.repo_url),Ze(!1)):je?(El("该项目未绑定仓库,环境无法创建——先选一个仓库保存"),Ze(!0)):(El(""),Ze(!1))}catch(qt){ae("加载失败:"+qt.message)}},[V]),Za=v.useCallback(async z=>{const w=z!==void 0?z:Vt.current;if(!w){mt([]);return}try{const W=await tt($.projectMembers(w));mt(W.members||[]),Tt("")}catch(W){Tt("成员加载失败:"+Oc(W))}},[]),va=v.useCallback(async z=>{const w=z!==void 0?z:Vt.current;if(!w){ie([]),ze([]),R([]),K("先选项目");return}K("");try{const W=await tt($.projectSkills(w));ie(W.skills||[])}catch(W){ht("技能加载失败:"+W.message)}try{const W=await tt($.projectApps(w));ze(W.apps||[])}catch(W){ht("应用加载失败:"+W.message)}try{const W=await tt($.projectMcp(w));R(W.servers||W.mcp_servers||[])}catch(W){ht("MCP 服务加载失败:"+W.message)}},[]),ou=v.useCallback(z=>{if(!z.trim()){o("key 为空,未保存");return}Xy(z.trim()),r(!0),o("已保存到本浏览器(只用于调本站 API)")},[]),du=v.useCallback(()=>{Vy(),r(!1),o("未填 key,数据接口会返回 401"),La()},[La]),$l=v.useCallback(async(z,w)=>{if(!z.trim()){Xt("项目名必填");return}const W={name:z.trim()};w.trim()&&(W.repo_url=w.trim());try{await tt($.projects,"POST",W),Xt("项目已建"),await $t()}catch(qt){Xt("新建失败:"+qt.message)}},[$t]),Se=v.useCallback(async(z,w,W)=>{const qt=Vt.current;if(!qt){ae("先选项目");return}if(!z.trim()){ae("环境名必填");return}const Lt={project_id:qt,name:z.trim()};w.trim()&&(Lt.branch=w.trim()),W&&(Lt.executor=W);try{await tt($.environmentsCreate,"POST",Lt),ae("环境已建,worker 准备中(creating → ready,失败会在列表里写原因)"),await Ke(qt)}catch(je){ae("新建失败:"+je.message)}},[Ke]),hl=v.useCallback(async z=>{if(window.confirm("确定归档该环境吗?归档后新任务不能再选它,进行中的任务不受影响(有进行中任务在用它时归档会被拒绝)。"))try{await tt($.environmentArchive(z),"POST",{}),await Ke()}catch(w){ae("归档失败:"+w.message)}},[Ke]),be=v.useCallback(async z=>{const w=Vt.current;if(!w){qe("先选项目");return}if(!z){qe("先选一个仓库");return}try{await tt($.project(w),"PATCH",{repo_url:z}),qe("仓库已保存,现在可以建环境了"),await $t(),await Ke(w)}catch(W){qe("保存失败:"+W.message)}},[$t,Ke]),H=v.useCallback(async(z,w)=>{const W=Vt.current;if(!W){A("先选项目");return}if(!z.trim()){A("请填成员 user_id 或用户名");return}try{await tt($.projectMembers(W),"POST",{user_id:z.trim(),role:w})}catch(qt){if(qt.message.includes("user not found"))try{await tt($.projectMembers(W),"POST",{username:z.trim(),role:w})}catch(Lt){A(Oc(Lt));return}else{A(Oc(qt));return}}A("已邀请成员"),await Za(W)},[Za]),D=v.useCallback(async(z,w)=>{const W=Vt.current;if(W)try{await tt($.projectMember(W,z),"PATCH",{role:w}),mt(qt=>qt.map(Lt=>Lt.user_id===z?{...Lt,role:w}:Lt)),A("角色已改为 "+w)}catch(qt){A(Oc(qt))}},[]),L=v.useCallback(async()=>{const z=Vt.current;if(!z){k("先选项目");return}try{await tt($.projectMcpReload(z),"POST",{}),k("配置已重载"),await va(z)}catch(w){k("重载失败:"+w.message)}},[va]),J=v.useCallback(async z=>{const w=Vt.current;if(!w){ge("先选项目");return}if(!z.trim()){ge("服务名不能为空");return}try{const W=await tt($.projectMcpOauth(w,z.trim()),"POST",{}),qt=W.url||W.auth_url||W.login_url||W.authorization_url||"",Lt=W.steps||W.instructions||"";let je=`登录尚未完成:请在浏览器打开下面的链接或按步骤完成,完成后回到本页刷新 MCP 状态。 -`;qt&&(je+=qt+` -`),Lt&&(je+=(Array.isArray(Lt)?Lt.join(` +`+a.stack}}var Vt=Object.prototype.hasOwnProperty,ll=i.unstable_scheduleCallback,ml=i.unstable_cancelCallback,ql=i.unstable_shouldYield,La=i.unstable_requestPaint,$t=i.unstable_now,Wl=i.unstable_getCurrentPriorityLevel,yn=i.unstable_ImmediatePriority,gn=i.unstable_UserBlockingPriority,Ke=i.unstable_NormalPriority,Za=i.unstable_LowPriority,va=i.unstable_IdlePriority,ou=i.log,du=i.unstable_setDisableYieldValue,$l=null,Se=null;function hl(t){if(typeof ou=="function"&&du(t),Se&&typeof Se.setStrictMode=="function")try{Se.setStrictMode($l,t)}catch{}}var be=Math.clz32?Math.clz32:L,H=Math.log,D=Math.LN2;function L(t){return t>>>=0,t===0?32:31-(H(t)/D|0)|0}var J=256,Ct=262144,Nl=4194304;function De(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&-t;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function z(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var n=0,u=t.suspendedLanes,c=t.pingedLanes;t=t.warmLanes;var f=a&134217727;return f!==0?(a=f&~u,a!==0?n=De(a):(c&=f,c!==0?n=De(c):l||(l=f&~t,l!==0&&(n=De(l))))):(f=a&~u,f!==0?n=De(f):c!==0?n=De(c):l||(l=a&~t,l!==0&&(n=De(l)))),n===0?0:e!==0&&e!==n&&(e&u)===0&&(u=n&-n,l=e&-e,u>=l||u===32&&(l&4194048)!==0)?e:n}function w(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function W(t,e){(e&8)!==0&&(e|=e&32);var l=t.entangledLanes;if(l!==0)for(t=t.entanglements,l&=e;0l;l++)e.push(t);return e}function Ue(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function ya(t,e,l,a,n,u){var c=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var f=t.entanglements,d=t.expirationTimes,S=t.hiddenUpdates;for(l=c&~l;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),wc=!1;if(ea)try{var gu={};Object.defineProperty(gu,"passive",{get:function(){wc=!0}}),window.addEventListener("test",gu,gu),window.removeEventListener("test",gu,gu)}catch{wc=!1}var ga=null,Gc=null,mi=null;function Rr(){if(mi)return mi;var t,e=Gc,l=e.length,a,n="value"in ga?ga.value:ga.textContent,u=n.length;for(t=0;t=bu),Yr=" ",wr=!1;function Gr(t,e){switch(t){case"keyup":return Av.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Qr(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Nn=!1;function Ov(t,e){switch(t){case"compositionend":return Qr(e);case"keypress":return e.which!==32?null:(wr=!0,Yr);case"textInput":return t=e.data,t===Yr&&wr?null:t;default:return null}}function zv(t,e){if(Nn)return t==="compositionend"||!Lc&&Gr(t,e)?(t=Rr(),mi=Gc=ga=null,Nn=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1"u")return null;try{return t.activeElement||t.body}catch{return t.body}}function Fr(t){for(;t&&t.firstChild;)t=t.firstChild;return t}function Wr(t,e){var l=Fr(t);t=0;for(var a;l;){if(l.nodeType===3){if(a=t+l.textContent.length,t<=e&&a>=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=Fr(l)}}function $r(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?$r(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function Ir(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=Jc(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=Jc(t.document)}return e}function Fc(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var wv=ea&&"documentMode"in document&&11>=document.documentMode,Cn=null,Wc=null,_u=null,$c=!1;function Pr(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;$c||Cn==null||Cn!==Jc(a)||(a=Cn,"selectionStart"in a&&Fc(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),_u&&Tu(_u,a)||(_u=a,a=pc(Wc,"onSelect"),0>=c,n-=c,wl=1<<32-be(e)+n|l<it?(re=P,P=null):re=P.sibling;var Et=g(p,P,j[it],M);if(Et===null){P===null&&(P=re);break}t&&P&&Et.alternate===null&&e(p,P),h=u(Et,h,it),jt===null?X=Et:jt.sibling=Et,jt=Et,P=re}if(it===j.length)return l(p,P),vt&&ua(p,it),X;if(P===null){for(;itit?(re=P,P=null):re=P.sibling;var ka=g(p,P,Et.value,M);if(ka===null){P===null&&(P=re);break}t&&P&&ka.alternate===null&&e(p,P),h=u(ka,h,it),jt===null?X=ka:jt.sibling=ka,jt=ka,P=re}if(Et.done)return l(p,P),vt&&ua(p,it),X;if(P===null){for(;!Et.done;it++,Et=j.next())Et=O(p,Et.value,M),Et!==null&&(h=u(Et,h,it),jt===null?X=Et:jt.sibling=Et,jt=Et);return vt&&ua(p,it),X}for(P=a(P);!Et.done;it++,Et=j.next())Et=T(P,p,it,Et.value,M),Et!==null&&(t&&(re=Et.alternate,re!==null&&P.delete(re.key===null?it:re.key)),h=u(Et,h,it),jt===null?X=Et:jt.sibling=Et,jt=Et);return t&&P.forEach(function(Oy){return e(p,Oy)}),vt&&ua(p,it),X}function rt(p,h,j,M){if(typeof j=="object"&&j!==null&&j.type===Kt&&j.key===null&&j.props.ref===void 0&&(j=j.props.children),typeof j=="object"&&j!==null){switch(j.$$typeof){case le:t:{for(var X=j.key;h!==null;){if(h.key===X){if(X=j.type,X===Kt){if(h.tag===7){l(p,h.sibling),M=n(h,j.props.children),Ta(M,j),M.return=p,p=M;break t}}else if(h.elementType===X||typeof X=="object"&&X!==null&&X.$$typeof===gt&&un(X)===h.type){l(p,h.sibling),M=n(h,j.props),Ta(M,j),M.return=p,p=M;break t}l(p,h);break}else e(p,h);h=h.sibling}j.type===Kt?(M=Ia(j.props.children,p.mode,M,j.key),Ta(M,j),M.return=p,p=M):(M=Ti(j.type,j.key,j.props,null,p.mode,M),Ta(M,j),M.return=p,p=M)}return c(p);case de:t:{for(X=j.key;h!==null;){if(h.key===X)if(h.tag===4&&h.stateNode.containerInfo===j.containerInfo&&h.stateNode.implementation===j.implementation){l(p,h.sibling),M=n(h,j.children||[]),M.return=p,p=M;break t}else{l(p,h);break}else e(p,h);h=h.sibling}M=ns(j,p.mode,M),M.return=p,p=M}return c(p);case gt:return j=un(j),rt(p,h,j,M)}if(_t(j))return q(p,h,j,M);if(K(j)){if(X=K(j),typeof X!="function")throw Error(o(150));return j=X.call(j),Z(p,h,j,M)}if(typeof j.then=="function")return rt(p,h,Di(j),M);if(j.$$typeof===mt)return rt(p,h,Mi(p,j),M);Ui(p,j)}return typeof j=="string"&&j!==""||typeof j=="number"||typeof j=="bigint"?(j=""+j,h!==null&&h.tag===6?(l(p,h.sibling),M=n(h,j),M.return=p,p=M):(l(p,h),M=as(j,p.mode,M),M.return=p,p=M),c(p)):l(p,h)}return function(p,h,j,M){try{Ou=0;var X=rt(p,h,j,M);return Bn=null,X}catch(P){if(P===Hn||P===zi)throw P;var jt=Fe(29,P,null,p.mode);return jt.lanes=M,jt.return=p,jt}finally{}}}var sn=_o(!0),Eo=_o(!1),_a=!1;function hs(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function vs(t,e){t=t.updateQueue,e.updateQueue===t&&(e.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Ea(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Na(t,e,l){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(At&2)!==0){var n=a.pending;return n===null?e.next=e:(e.next=n.next,n.next=e),a.pending=e,e=ji(t),co(t,null,l),e}return xi(t,a,e,l),ji(t)}function zu(t,e,l){if(e=e.updateQueue,e!==null&&(e=e.shared,(l&4194048)!==0)){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,ii(t,l)}}function ys(t,e){var l=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var c={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=c:u=u.next=c,l=l.next}while(l!==null);u===null?n=u=e:u=u.next=e}else n=u=e;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},t.updateQueue=l;return}t=l.lastBaseUpdate,t===null?l.firstBaseUpdate=e:t.next=e,l.lastBaseUpdate=e}var gs=!1;function Ru(){if(gs){var t=Un;if(t!==null)throw t}}function Du(t,e,l,a){gs=!1;var n=t.updateQueue;_a=!1;var u=n.firstBaseUpdate,c=n.lastBaseUpdate,f=n.shared.pending;if(f!==null){n.shared.pending=null;var d=f,S=d.next;d.next=null,c===null?u=S:c.next=S,c=d;var E=t.alternate;E!==null&&(E=E.updateQueue,f=E.lastBaseUpdate,f!==c&&(f===null?E.firstBaseUpdate=S:f.next=S,E.lastBaseUpdate=d))}if(u!==null){var O=n.baseState;c=0,E=S=d=null,f=u;do{var g=f.lane&-536870913,T=g!==f.lane;if(T?(xt&g)===g:(a&g)===g){g!==0&&g===an&&(gs=!0),E!==null&&(E=E.next={lane:0,tag:f.tag,payload:f.payload,callback:null,next:null});t:{var q=t,Z=f;g=e;var rt=l;switch(Z.tag){case 1:if(q=Z.payload,typeof q=="function"){O=q.call(rt,O,g);break t}O=q;break t;case 3:q.flags=q.flags&-65537|128;case 0:if(q=Z.payload,g=typeof q=="function"?q.call(rt,O,g):q,g==null)break t;O=ct({},O,g);break t;case 2:_a=!0}}g=f.callback,g!==null&&(t.flags|=64,T&&(t.flags|=8192),T=n.callbacks,T===null?n.callbacks=[g]:T.push(g))}else T={lane:g,tag:f.tag,payload:f.payload,callback:f.callback,next:null},E===null?(S=E=T,d=O):E=E.next=T,c|=g;if(f=f.next,f===null){if(f=n.shared.pending,f===null)break;T=f,f=T.next,T.next=null,n.lastBaseUpdate=T,n.shared.pending=null}}while(!0);E===null&&(d=O),n.baseState=d,n.firstBaseUpdate=S,n.lastBaseUpdate=E,u===null&&(n.shared.lanes=0),Da|=c,t.lanes=c,t.memoizedState=O}}function No(t,e){if(typeof t!="function")throw Error(o(191,t));t.call(e)}function Co(t,e){var l=t.callbacks;if(l!==null)for(t.callbacks=null,t=0;tu?u:8;var c=k.T,f={};f.types=c!==null?c.types:null,k.T=f,qs(t,!1,e,l);try{var d=n(),S=k.S;if(S!==null&&S(f,d),d!==null&&typeof d=="object"&&typeof d.then=="function"){var E=Wv(d,a);qu(t,e,E,fl(t))}else qu(t,e,a,fl(t))}catch(O){qu(t,e,{then:function(){},status:"rejected",reason:O},fl())}finally{ut.p=u,c!==null&&f.types!==null&&(c.types=f.types),k.T=c}}function l0(){}function Hs(t,e,l,a){if(t.tag!==5)throw Error(o(476));var n=ud(t).queue;nd(t,n,e,ge,l===null?l0:function(){return id(t),l(a)})}function ud(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:ge,baseState:ge,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:fa,lastRenderedState:ge},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:fa,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function id(t){var e=ud(t);e.next===null&&(e=t.alternate.memoizedState),qu(t,e.next.queue,{},fl())}function Bs(){return Te(nu)}function cd(){return ue().memoizedState}function sd(){return ue().memoizedState}function a0(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=fl();t=Ea(l);var a=Na(e,t,l);a!==null&&(Pe(a,e,l),zu(a,e,l)),e={cache:rs()},t.payload=e;return}e=e.return}}function n0(t,e,l){var a=fl();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Vi(t)?rd(e,l):(l=es(t,e,l,a),l!==null&&(Pe(l,t,a),od(l,e,a)))}function fd(t,e,l){var a=fl();qu(t,e,l,a)}function qu(t,e,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Vi(t))rd(e,n);else{var u=t.alternate;if(t.lanes===0&&(u===null||u.lanes===0)&&(u=e.lastRenderedReducer,u!==null))try{var c=e.lastRenderedState,f=u(c,l);if(n.hasEagerState=!0,n.eagerState=f,nl(f,c))return xi(t,e,n,0),wt===null&&bi(),!1}catch{}finally{}if(l=es(t,e,n,a),l!==null)return Pe(l,t,a),od(l,e,a),!0}return!1}function qs(t,e,l,a){if(a={lane:2,revertLane:Af(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Vi(t)){if(e)throw Error(o(479))}else e=es(t,l,a,2),e!==null&&Pe(e,t,2)}function Vi(t){var e=t.alternate;return t===ft||e!==null&&e===ft}function rd(t,e){qn=qi=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function od(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,ii(t,l)}}var Li={readContext:Te,use:Gi,useCallback:It,useContext:It,useEffect:It,useImperativeHandle:It,useLayoutEffect:It,useInsertionEffect:It,useMemo:It,useReducer:It,useRef:It,useState:It,useDebugValue:It,useDeferredValue:It,useTransition:It,useSyncExternalStore:It,useId:It,useHostTransitionStatus:It,useFormState:It,useActionState:It,useOptimistic:It,useMemoCache:It,useCacheRefresh:It,useEffectEvent:It},dd={readContext:Te,use:Gi,useCallback:function(t,e){return Qe().memoizedState=[t,e===void 0?null:e],t},useContext:Te,useEffect:Fo,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,ki(4194308,4,Po.bind(null,e,t),l)},useLayoutEffect:function(t,e){return ki(4194308,4,t,e)},useInsertionEffect:function(t,e){ki(4,2,t,e)},useMemo:function(t,e){var l=Qe();e=e===void 0?null:e;var a=t();if(fn){hl(!0);try{t()}finally{hl(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=Qe();if(l!==void 0){var n=l(e);if(fn){hl(!0);try{l(e)}finally{hl(!1)}}}else n=e;return a.memoizedState=a.baseState=n,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:n},a.queue=t,t=t.dispatch=n0.bind(null,ft,t),[a.memoizedState,t]},useRef:function(t){var e=Qe();return t={current:t},e.memoizedState=t},useState:function(t){t=Os(t);var e=t.queue,l=fd.bind(null,ft,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:Ds,useDeferredValue:function(t,e){var l=Qe();return Us(l,t,e)},useTransition:function(){var t=Os(!1);return t=nd.bind(null,ft,t.queue,!0,!1),Qe().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=ft,n=Qe();if(vt){if(l===void 0)throw Error(o(407));l=l()}else{if(l=e(),wt===null)throw Error(o(349));(xt&127)!==0||Do(a,e,l)}n.memoizedState=l;var u={value:l,getSnapshot:e};return n.queue=u,Fo(Ho.bind(null,a,u,t),[t]),a.flags|=2048,wn(9,{destroy:void 0},Uo.bind(null,a,u,l,e),null),l},useId:function(){var t=Qe(),e=wt.identifierPrefix;if(vt){var l=Gl,a=wl;l=(a&~(1<<32-be(a)-1)).toString(32)+l,e="_"+e+"R_"+l,l=Yi++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?c.createElement("select",{is:a.is}):c.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?c.createElement(n,{is:a.is}):c.createElement(n)}}u[je]=e,u[Je]=a;t:for(c=e.child;c!==null;){if(c.tag===5||c.tag===6)u.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===e)break t;for(;c.sibling===null;){if(c.return===null||c.return===e)break t;c=c.return}c.sibling.return=c.return,c=c.sibling}e.stateNode=u;t:switch(Ce(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&oa(e)}}return kt(e),e.subtreeFlags&=-33554433,Ws(e,e.type,t===null?null:t.memoizedProps,e.pendingProps,l),null;case 6:if(t&&e.stateNode!=null)t.memoizedProps!==a&&oa(e);else{if(typeof a!="string"&&e.stateNode===null)throw Error(o(166));if(t=ae.current,Dn(e)){if(t=e.stateNode,l=e.memoizedProps,a=null,n=he,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}t[je]=e,t=!!(t.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||Hm(t.nodeValue,l)),t||xa(e,!0)}else t=Wu(t).createTextNode(a),t[je]=e,e.stateNode=t}return kt(e),null;case 31:if(l=e.memoizedState,t===null||t.memoizedState!==null){if(a=Dn(e),l!==null){if(t===null){if(!a)throw Error(o(318));if(t=e.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(o(557));t[je]=e}else Pa(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;kt(e),t=!1}else l=cs(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=l),t=!0;if(!t)return e.flags&256?(ul(e),e):(ul(e),null);if((e.flags&128)!==0)throw Error(o(558))}return kt(e),null;case 13:if(a=e.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(n=Dn(e),a!==null&&a.dehydrated!==null){if(t===null){if(!n)throw Error(o(318));if(n=e.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(o(317));n[je]=e}else Pa(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;kt(e),n=!1}else n=cs(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=n),n=!0;if(!n)return e.flags&256?(ul(e),e):(ul(e),null)}return ul(e),(e.flags&128)!==0?(e.lanes=l,e):(l=a!==null,t=t!==null&&t.memoizedState!==null,l&&(a=e.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==t&&l&&(e.child.flags|=8192),$i(e,e.updateQueue),kt(e),null);case 4:return el(),t===null&&Rf(e.stateNode.containerInfo),e.flags|=67108864,kt(e),null;case 10:return ca(e.type),kt(e),null;case 19:if(xs(e),a=e.memoizedState,a===null)return kt(e),null;if(n=(e.flags&128)!==0,u=a.rendering,u===null)if(n)wu(a,!1);else{if(Pt!==0||t!==null&&(t.flags&128)!==0)for(t=e.child;t!==null;){if(u=Bi(t),u!==null){for(e.flags|=128,wu(a,!1),t=u.updateQueue,e.updateQueue=t,$i(e,t),e.subtreeFlags=0,t=l,l=e.child;l!==null;)so(l,t),l=l.sibling;return Uu(e,Ee.current&1|2),vt&&ua(e,a.treeForkCount),e.child}t=t.sibling}a.tail!==null&&$t()>fc&&(e.flags|=128,n=!0,wu(a,!1),e.lanes=4194304)}else{if(!n)if(t=Bi(u),t!==null){if(e.flags|=128,n=!0,t=t.updateQueue,e.updateQueue=t,$i(e,t),wu(a,!0),a.tail===null&&a.tailMode!=="collapsed"&&a.tailMode!=="visible"&&!u.alternate&&!vt)return kt(e),null}else 2*$t()-a.renderingStartTime>fc&&l!==536870912&&(e.flags|=128,n=!0,wu(a,!1),e.lanes=4194304);a.isBackwards?(u.sibling=e.child,e.child=u):(t=a.last,t!==null?t.sibling=u:e.child=u,a.last=u)}if(a.tail!==null){t=a.tail;t:{for(l=t;l!==null;){if(l.alternate!==null){l=!1;break t}l=l.sibling}l=!0}return a.rendering=t,a.tail=t.sibling,a.renderingStartTime=$t(),t.sibling=null,u=Ee.current,u=n?u&1|2:u&1,a.tailMode==="visible"||a.tailMode==="collapsed"||!l||vt?Uu(e,u):(l=u,zt(_e,e),zt(Ee,l),Be===null&&(Be=e)),vt&&ua(e,a.treeForkCount),t}return kt(e),null;case 22:case 23:return ul(e),Ss(),a=e.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(e.flags|=8192):a&&(e.flags|=8192),a?(l&536870912)!==0&&(e.flags&128)===0&&(kt(e),e.subtreeFlags&6&&(e.flags|=8192)):kt(e),l=e.updateQueue,l!==null&&$i(e,l.retryQueue),l=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(l=t.memoizedState.cachePool.pool),a=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),a!==l&&(e.flags|=2048),t!==null&&Gt(nn),null;case 24:return l=null,t!==null&&(l=t.memoizedState.cache),e.memoizedState.cache!==l&&(e.flags|=2048),ca(ce),kt(e),null;case 25:return null;case 30:return e.flags|=33554432,kt(e),null}throw Error(o(156,e.tag))}function o0(t,e){switch(us(e),e.tag){case 1:return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 3:return ca(ce),el(),t=e.flags,(t&65536)!==0&&(t&128)===0?(e.flags=t&-65537|128,e):null;case 26:case 27:case 5:return ne(e),null;case 31:if(e.memoizedState!==null){if(ul(e),e.alternate===null)throw Error(o(340));Pa()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 13:if(ul(e),t=e.memoizedState,t!==null&&t.dehydrated!==null){if(e.alternate===null)throw Error(o(340));Pa()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 19:return xs(e),t=e.flags,t&65536?(e.flags=t&-65537|128,t=e.memoizedState,t!==null&&(t.rendering=null,t.tail=null),e.flags|=4,e):null;case 4:return el(),null;case 10:return ca(e.type),null;case 22:case 23:return ul(e),Ss(),t!==null&&Gt(nn),t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 24:return ca(ce),null;case 25:return null;default:return null}}function qd(t,e){switch(us(e),e.tag){case 3:ca(ce),el();break;case 26:case 27:case 5:ne(e);break;case 4:el();break;case 31:e.memoizedState!==null&&ul(e);break;case 13:ul(e);break;case 19:xs(e);break;case 10:ca(e.type);break;case 22:case 23:ul(e),Ss(),t!==null&&Gt(nn);break;case 24:ca(ce)}}function Gu(t,e){try{var l=e.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&t)===t){a=void 0;var u=l.create,c=l.inst;a=u(),c.destroy=a}l=l.next}while(l!==n)}}catch(f){Ht(e,e.return,f)}}function Oa(t,e,l){try{var a=e.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&t)===t){var c=a.inst,f=c.destroy;if(f!==void 0){c.destroy=void 0,n=e;var d=l,S=f;try{S()}catch(E){Ht(n,d,E)}}}a=a.next}while(a!==u)}}catch(E){Ht(e,e.return,E)}}function Yd(t){var e=t.updateQueue;if(e!==null){var l=t.stateNode;try{Co(e,l)}catch(a){Ht(t,t.return,a)}}}function wd(t,e,l){l.props=rn(t.type,t.memoizedProps),l.state=t.memoizedState;try{l.componentWillUnmount()}catch(a){Ht(t,e,a)}}function Ql(t,e){try{var l=t.ref;if(l!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:var n=t.stateNode,u=la(t.memoizedProps,n);(n.ref===null||n.ref.name!==u)&&(n.ref=Zm(u)),a=n.ref;break;case 7:if(t.stateNode===null){var c=new rl(t);b(t.child,!1,ey,c,void 0,void 0),t.stateNode=c}a=t.stateNode;break;default:a=t.stateNode}typeof l=="function"?t.refCleanup=l(a):l.current=a}}catch(f){Ht(t,e,f)}}function Ne(t,e){var l=t.ref,a=t.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Ht(t,e,n)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){Ht(t,e,n)}else l.current=null}function Ii(t,e){if((t.tag===5||t.tag===27||t.tag===6)&&t.alternate===null&&e!==null)for(var l=0;l title"))),Ce(a,e,l),a[je]=t,me(a),e=a;break t;case"link":if(u=fh("link","href",n).get(e+(l.href||""))){for(c=0;crt&&(c=rt,rt=Z,Z=c);var p=Wr(f,Z),h=Wr(f,rt);if(p&&h&&(T.rangeCount!==1||T.anchorNode!==p.node||T.anchorOffset!==p.offset||T.focusNode!==h.node||T.focusOffset!==h.offset)){var j=O.createRange();j.setStart(p.node,p.offset),T.removeAllRanges(),Z>rt?(T.addRange(j),T.extend(h.node,h.offset)):(j.setEnd(h.node,h.offset),T.addRange(j))}}}}for(O=[],T=f;T=T.parentNode;)T.nodeType===1&&O.push({element:T,left:T.scrollLeft,top:T.scrollTop});for(typeof f.focus=="function"&&f.focus(),f=0;fl?32:l,k.T=null,l=pf,pf=null;var u=zl,c=Kl;if(Jt=0,hn=zl=null,Kl=0,(At&6)!==0)throw Error(o(331));var f=At;if(At|=4,sm(u.current),um(u,u.current,c,l),At=f,Ku(0,!1),Se&&typeof Se.onPostCommitFiberRoot=="function")try{Se.onPostCommitFiberRoot($l,u)}catch{}return!0}finally{ut.p=n,k.T=a,Tm(t,e)}}function _m(t,e,l){e=gl(l,e),e=Gs(t.stateNode,e,2),t=Na(t,e,2),t!==null&&(Ue(t,2),Jl(t))}function Ht(t,e,l){if(t.tag===3)_m(t,t,l);else for(;e!==null;){if(e.tag===3){_m(e,t,l);break}else if(e.tag===1){var a=e.stateNode;if(typeof e.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Ua===null||!Ua.has(a))){t=gl(l,t),l=bd(2),a=Na(e,l,2),a!==null&&(xd(l,a,e,t),Ue(a,2),Jl(a));break}}e=e.return}}function Ef(t,e,l){var a=t.pingCache;if(a===null){a=t.pingCache=new v0;var n=new Set;a.set(e,n)}else n=a.get(e),n===void 0&&(n=new Set,a.set(e,n));n.has(l)||(vf=!0,n.add(l),t=T0.bind(null,t,e,l),e.then(t,t))}function T0(t,e,l){var a=t.pingCache;a!==null&&a.delete(e),t.pingedLanes|=t.suspendedLanes&l,t.warmLanes&=~l,wt===t&&(xt&l)===l&&((Pt===4||Pt===3&&(xt&62914560)===xt&&300>$t()-sc)&&(At&2)===0?Wn(t,0):cc|=l,Ln===xt&&(Ln=0)),Jl(t)}function Em(t,e){e===0&&(e=Lt()),t=$a(t,e),t!==null&&(Ue(t,e),Jl(t))}function _0(t){var e=t.memoizedState,l=0;e!==null&&(l=e.retryLane),Em(t,l)}function E0(t,e){var l=0;switch(t.tag){case 31:case 13:var a=t.stateNode,n=t.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(o(314))}a!==null&&a.delete(e),Em(t,l)}function N0(t,e){return ll(t,e)}var In=null,Pn=null,Nf=!1,yc=!1,Cf=!1,Ba=0;function Jl(t){t!==Pn&&t.next===null&&(Pn===null?In=Pn=t:Pn=Pn.next=t),yc=!0,Nf||(Nf=!0,A0())}function Ku(t,e){if(!Cf&&yc){Cf=!0;do for(var l=!1,a=In;a!==null;){if(t!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var c=a.suspendedLanes,f=a.pingedLanes;u=(1<<31-be(42|t)+1)-1,u&=n&~(c&~f),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,Mm(a,u))}else u=xt,u=z(a,a===wt?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||w(a,u)||(l=!0,Mm(a,u));a=a.next}while(l);Cf=!1}}function C0(){Nm()}function Nm(){yc=Nf=!1;var t=0;Ba!==0&&w0()&&(t=Ba);for(var e=$t(),l=null,a=In;a!==null;){var n=a.next,u=Cm(a,e);u===0?(a.next=null,l===null?In=n:l.next=n,n===null&&(Pn=l)):(l=a,(t!==0||(u&3)!==0)&&(yc=!0)),a=n}Jt!==0&&Jt!==5||Ku(t),Ba!==0&&(Ba=0)}function Cm(t,e){for(var l=t.suspendedLanes,a=t.pingedLanes,n=t.expirationTimes,u=t.pendingLanes&-62914561;0f)break;var E=d.transferSize,O=d.initiatorType;E&&Bm(O)&&(d=d.responseEnd,c+=E*(dxc){Z.length=q;break}j=new Promise(L0.bind(j)),Z.push(j)}}}if(0"u"?null:document;function uh(t,e,l){var a=eu;if(a&&typeof e=="string"&&e){var n=vl(e);n='link[rel="'+t+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),nh.has(n)||(nh.add(n),t={rel:t,crossOrigin:l,href:e},a.querySelector(n)===null&&(e=a.createElement("link"),Ce(e,"link",t),me(e),a.head.appendChild(e)))}}function ry(t){ma.D(t),uh("dns-prefetch",t,null)}function oy(t,e){ma.C(t,e),uh("preconnect",t,e)}function dy(t,e,l){ma.L(t,e,l);var a=eu;if(a&&t&&e){var n='link[rel="preload"][as="'+vl(e)+'"]';e==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+vl(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+vl(l.imageSizes)+'"]')):n+='[href="'+vl(t)+'"]';var u=n;switch(e){case"style":u=lu(t);break;case"script":u=au(t)}if(!(Tl.has(u)||(t=ct({rel:"preload",href:e==="image"&&l&&l.imageSrcSet?void 0:t,as:e},l),Tl.set(u,t),a.querySelector(n)!==null||e==="style"&&a.querySelector(Iu(u))||e==="script"&&a.querySelector(Pu(u))))){var c=a.createElement("link");Ce(c,"link",t),e==="style"&&(c[si]=!0,c.onload=c.onerror=function(){gr(c)}),me(c),a.head.appendChild(c)}}}function my(t,e){ma.m(t,e);var l=eu;if(l&&t){var a=e&&typeof e.as=="string"?e.as:"script",n='link[rel="modulepreload"][as="'+vl(a)+'"][href="'+vl(t)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=au(t)}if(!Tl.has(u)&&(t=ct({rel:"modulepreload",href:t},e),Tl.set(u,t),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(Pu(u)))return}a=l.createElement("link"),Ce(a,"link",t),me(a),l.head.appendChild(a)}}}function hy(t,e,l){ma.S(t,e,l);var a=eu;if(a&&t){var n=bn(a).hoistableStyles,u=lu(t);e=e||"default";var c=n.get(u);if(!c){var f={loading:0,preload:null};if(c=a.querySelector(Iu(u)))f.loading=5;else{t=ct({rel:"stylesheet",href:t,"data-precedence":e},l),(l=Tl.get(u))&&Jf(t,l);var d=c=a.createElement("link");me(d),Ce(d,"link",t),d._p=new Promise(function(S,E){d.onload=S,d.onerror=E}),d.addEventListener("load",function(){f.loading|=1}),d.addEventListener("error",function(){f.loading|=2}),f.loading|=4,Sc(c,e,a)}c={type:"stylesheet",instance:c,count:1,state:f},n.set(u,c)}}}function vy(t,e){ma.X(t,e);var l=eu;if(l&&t){var a=bn(l).hoistableScripts,n=au(t),u=a.get(n);u||(u=l.querySelector(Pu(n)),u||(t=ct({src:t,async:!0},e),(e=Tl.get(n))&&Ff(t,e),u=l.createElement("script"),me(u),Ce(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function yy(t,e){ma.M(t,e);var l=eu;if(l&&t){var a=bn(l).hoistableScripts,n=au(t),u=a.get(n);u||(u=l.querySelector(Pu(n)),u||(t=ct({src:t,async:!0,type:"module"},e),(e=Tl.get(n))&&Ff(t,e),u=l.createElement("script"),me(u),Ce(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function ih(t,e,l,a){var n=(n=ae.current)?$u(n):null;if(!n)throw Error(o(446));switch(t){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(l=lu(l.href),e=bn(n).hoistableStyles,a=e.get(l),a||(a={type:"style",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){t=lu(l.href);var u=bn(n).hoistableStyles,c=u.get(t);if(c||(n=n.ownerDocument||n,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(t,c),(u=n.querySelector(Iu(t)))?u._p||(c.instance=u,c.state.loading=5):(u=Tl.get(t),u||(u={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Tl.set(t,u)),gy(n,t,u,c.state))),e&&a===null)throw Error(o(528,""));return c}if(e&&a!==null)throw Error(o(529,""));return null;case"script":return e=l.async,l=l.src,typeof l=="string"&&e&&typeof e!="function"&&typeof e!="symbol"?(l=au(l),e=bn(n).hoistableScripts,a=e.get(l),a||(a={type:"script",instance:null,count:0,state:null},e.set(l,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,t))}}function lu(t){return'href="'+vl(t)+'"'}function Iu(t){return'link[rel="stylesheet"]['+t+"]"}function ch(t){return ct({},t,{"data-precedence":t.precedence,precedence:null})}function gy(t,e,l,a){if(e=t.querySelector('link[rel="preload"][as="style"]['+e+"]")){if(e[si]!==!0){a.loading=1;return}}else e=t.createElement("link"),e[si]=!0,e.onload=e.onerror=gr.bind(null,e),Ce(e,"link",l),me(e),t.head.appendChild(e);a.preload=e,e.addEventListener("load",function(){return a.loading|=1}),e.addEventListener("error",function(){return a.loading|=2})}function au(t){return'[src="'+vl(t)+'"]'}function Pu(t){return"script[async]"+t}function sh(t,e,l){if(e.count++,e.instance===null)switch(e.type){case"style":var a=t.querySelector('style[data-href~="'+vl(l.href)+'"]');if(a)return e.instance=a,me(a),a;var n=ct({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),me(a),Ce(a,"style",n),Sc(a,l.precedence,t),e.instance=a;case"stylesheet":n=lu(l.href);var u=t.querySelector(Iu(n));if(u)return e.state.loading|=4,e.instance=u,me(u),u;a=ch(l),(n=Tl.get(n))&&Jf(a,n),u=(t.ownerDocument||t).createElement("link"),me(u);var c=u;return c._p=new Promise(function(f,d){c.onload=f,c.onerror=d}),Ce(u,"link",a),e.state.loading|=4,Sc(u,l.precedence,t),e.instance=u;case"script":return u=au(l.src),(n=t.querySelector(Pu(u)))?(e.instance=n,me(n),n):(a=l,(n=Tl.get(u))&&(a=ct({},l),Ff(a,n)),t=t.ownerDocument||t,n=t.createElement("script"),me(n),Ce(n,"link",a),t.head.appendChild(n),e.instance=n);case"void":return null;default:throw Error(o(443,e.type))}else e.type==="stylesheet"&&(e.state.loading&4)===0&&(a=e.instance,e.state.loading|=4,Sc(a,l.precedence,t));return e.instance}function Sc(t,e,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,c=0;c title"):null)}function py(t,e,l){if(l===1||e.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof e.precedence!="string"||typeof e.href!="string"||e.href==="")break;return!0;case"link":if(typeof e.rel!="string"||typeof e.href!="string"||e.href===""||e.onLoad||e.onError)break;switch(e.rel){case"stylesheet":return t=e.disabled,typeof e.precedence=="string"&&t==null;default:return!0}case"script":if(e.async&&typeof e.async!="function"&&typeof e.async!="symbol"&&!e.onLoad&&!e.onError&&e.src&&typeof e.src=="string")return!0}return!1}function rh(t,e){return t==="img"&&e.src!=null&&e.src!==""&&e.onLoad==null&&e.loading!=="lazy"}function oh(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function dh(t){return(t.width||100)*(t.height||100)*(typeof devicePixelRatio=="number"?devicePixelRatio:1)*.25}function mh(t,e){typeof e.decode=="function"&&(t.imgCount++,e.complete||(t.imgBytes+=dh(e),t.suspenseyImages.push(e)),t=xy.bind(t),e.decode().then(t,t))}function Sy(t,e,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=lu(a.href),u=e.querySelector(Iu(n));if(u){e=u._p,e!==null&&typeof e=="object"&&typeof e.then=="function"&&(t.count++,t=ti.bind(t),e.then(t,t)),l.state.loading|=4,l.instance=u,me(u);return}u=e.ownerDocument||e,a=ch(a),(n=Tl.get(n))&&Jf(a,n),u=u.createElement("link"),me(u);var c=u;c._p=new Promise(function(f,d){c.onload=f,c.onerror=d}),Ce(u,"link",a),l.instance=u}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(l,e),(e=l.state.preload)&&(l.state.loading&3)===0&&(t.count++,l=ti.bind(t),e.addEventListener("load",l),e.addEventListener("error",l))}}var xc=0;function by(t,e){return t.stylesheets&&t.count===0&&Tc(t,t.stylesheets),0xc?50:800)+e);return t.unsuspend=l,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function hh(t){if(t.count===0&&(t.imgCount===0||!t.waitingForImages)){if(t.stylesheets)Tc(t,t.stylesheets);else if(t.unsuspend){var e=t.unsuspend;t.unsuspend=null,e()}}}function ti(){this.count--,hh(this)}function xy(){this.imgCount--,hh(this)}var jc=null;function Tc(t,e){t.stylesheets=null,t.unsuspend!==null&&(t.count++,jc=new Map,e.forEach(jy,t),jc=null,ti.call(t))}function jy(t,e){if(!(e.state.loading&4)){var l=jc.get(t);if(l)var a=l.get(null);else{l=new Map,jc.set(t,l);for(var n=t.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(r){console.error(r)}}return i(),ur.exports=wy(),ur.exports}var Qy=Gy();const ky=wh(Qy),Gh=v.createContext(null);function Mt(){const i=v.useContext(Gh);if(!i)throw new Error("ConsoleContext missing");return i}const ot=encodeURIComponent,$={health:"/health",relayModels:"/relay/models",quotaMe:"/users/me/quota",userKeys:"/users/me/keys",userKey:i=>"/users/me/keys/"+ot(i),githubRepos:"/github/repos",projects:"/projects",project:i=>"/projects/"+ot(i),projectMembers:i=>"/projects/"+ot(i)+"/members",projectMember:(i,r)=>"/projects/"+ot(i)+"/members/"+ot(r),projectSkills:i=>"/projects/"+ot(i)+"/skills",projectApps:i=>"/projects/"+ot(i)+"/apps",projectMcp:i=>"/projects/"+ot(i)+"/mcp-servers",projectMcpReload:i=>"/projects/"+ot(i)+"/mcp-servers/reload",projectMcpOauth:(i,r)=>"/projects/"+ot(i)+"/mcp-servers/"+ot(r)+"/oauth-login",projectAutomations:i=>"/projects/"+ot(i)+"/automations",projectAutomationCancel:(i,r)=>"/projects/"+ot(i)+"/automations/"+ot(r)+"/cancel",projectTriage:i=>"/projects/"+ot(i)+"/triage",workers:"/workers",environments:i=>"/environments?project_id="+ot(i),environmentsCreate:"/environments",environmentArchive:i=>"/environments/"+ot(i)+"/archive",tasks:i=>"/tasks?project_id="+ot(i),tasksByParent:(i,r)=>"/tasks?project_id="+ot(i)+"&parent_task_id="+ot(r),tasksCreate:"/tasks",task:i=>"/tasks/"+ot(i),taskAction:(i,r)=>"/tasks/"+ot(i)+"/"+r,taskFork:i=>"/tasks/"+ot(i)+"/fork",taskContinue:i=>"/tasks/"+ot(i)+"/continue",taskTrace:i=>"/tasks/"+ot(i)+"/trace",taskTraceStream:i=>"/tasks/"+ot(i)+"/trace/stream",taskAgents:i=>"/tasks/"+ot(i)+"/agents",taskReviews:i=>"/tasks/"+ot(i)+"/reviews",taskReviewFindings:(i,r)=>"/tasks/"+ot(i)+"/reviews/"+ot(r)+"/findings",taskApprovals:i=>"/tasks/"+ot(i)+"/approvals",taskApprovalDecision:(i,r,m)=>"/tasks/"+ot(i)+"/approvals/"+ot(r)+"/"+m,taskFollowups:i=>"/tasks/"+ot(i)+"/followups",taskChatHistory:i=>"/tasks/"+ot(i)+"/chat-history",taskMessages:i=>"/tasks/"+ot(i)+"/messages",taskMessagesTo:i=>"/tasks/"+ot(i)+"/messages",taskThread:i=>"/tasks/"+ot(i)+"/thread",taskThreads:i=>"/tasks/"+ot(i)+"/threads",taskThreadAction:(i,r)=>"/tasks/"+ot(i)+"/thread/"+r,taskCost:i=>"/tasks/"+ot(i)+"/cost",uploads:"/uploads",adminQuotas:"/admin/quotas",adminQuotaUser:i=>"/admin/quotas?user_id="+ot(i),adminSweep:"/admin/sweep",adminBackup:"/admin/backup"},Xy={exec:"命令",file:"文件",call:"调用",tool:"工具",message:"消息",reasoning:"思考",plan:"计划","agent-start":"子代理","agent-done":"子代理"},su=["completed","failed","interrupted","merged","merge-failed"],Vy={queued:"排队中,尚未被 worker 认领",running:"运行中,模型回合进行中",completed:"模型回合结束、改动在 worktree 里尚未合并",failed:"模型回合失败,可重试",interrupted:"已被取消/中断,可重试",merged:"控制面已标记 merged,不代表 git 主分支已合入","merge-failed":"合并落盘失败,可重试"},Yh=["low","medium","high","xhigh","max"],Ly=["viewer","contributor","maintainer","owner"],mr="codex-console-key";function _l(){try{return localStorage.getItem(mr)||""}catch{return""}}function Zy(i){localStorage.setItem(mr,i)}function Ky(){localStorage.removeItem(mr)}function Me(i){return i?i.slice(0,8):""}function Xa(i){return i?new Date(i*1e3).toLocaleString():""}async function tt(i,r="GET",m){const o={"Content-Type":"application/json"},_=_l();_&&(o["X-API-Key"]=_);const C={method:r,headers:o};m!==void 0&&(C.body=JSON.stringify(m));const N=await fetch(i,C);let x=null;try{x=await N.json()}catch{x=null}if(!N.ok){const G=x;let U=G&&G.error?G.error:"HTTP "+N.status;throw N.status===401&&(U+="(key 未填或无效)"),N.status===429&&(U+="(触发限流,稍后再试)"),N.status===402&&(G&&G.unpriced_token_cap!==void 0?U+="(无价 token 已满,联系管理员调整)":G&&G.error==="coordinator_quota_reserve_exceeded"?U="协调员分工预留不足:剩余美元配额不够覆盖全部分工,子任务费用记父任务创建人账,整个父任务已被挡下(未建任何子任务)":U+="(美元配额已满,联系管理员调整)"),new Error(U)}return x}async function Jy(i){const r=new FormData;r.append("paths",JSON.stringify(i.map(_=>_.path))),i.forEach((_,C)=>r.append("file"+C,_.file));const m=await fetch($.uploads,{method:"POST",headers:{"X-API-Key":_l()},body:r}),o=await m.json().catch(()=>({}));if(!m.ok)throw new Error(o&&o.error||"HTTP "+m.status);return o.upload_id}function Fy(i,r,m){const o=[],_={},C=(N,x)=>{if(N)for(let G=0;GN.name),C(r,N=>N.webkitRelativePath||N.name),C(m,N=>N.name),o}function Qh(i){const r=Date.now()/1e3;let m=null;if(typeof i.last_seen=="number"?m=r-i.last_seen:typeof i.last_seen_seconds_ago=="number"&&(m=i.last_seen_seconds_ago),(m===null||m<0)&&(m=null),m===null)return{text:"未知",age:null};const o=Math.floor(m);return o<60?{text:o+" 秒前",age:m}:o<3600?{text:Math.floor(o/60)+" 分钟前",age:m}:{text:Math.floor(o/3600)+" 小时前",age:m}}function Oc(i){const r=i.message||"";return r.includes("forbidden")?"没有权限:只有项目 owner 或全局管理员可以管理成员":r.includes("already_member")?"该用户已是成员,改角色请用成员行的下拉框":r.includes("cannot demote the only owner")?"不能把唯一 owner 降为非 owner:请先把另一位成员升为 owner":r.includes("user not found")?"找不到该用户:请核对 user_id 或用户名是否正确":r.includes("member not found")?"该用户不是本项目成员":r.includes("unknown role")?"角色无效:只能是 viewer / contributor / maintainer / owner":r.includes("project not found")?"项目不存在(可能已被删除)":"成员操作失败:"+r}function fr(i){const r=i.message||"";return r.includes("forbidden")?"无全局管理员权限:服务端返回 403(CODEX_GLOBAL_ADMINS 未包含当前用户),请联系管理员":r.includes("user not found")?"找不到该用户:请核对用户 id 是否正确":"管理操作失败:"+r}function rr(i){return i==null?"不限额":"$"+(i/1e6).toFixed(2)}function or(i){const r=Xy[i.kind||""]||i.kind||"?";let m="";return i.kind==="exec"?m=(i.command||"")+"(exit="+(i.exitCode??"")+","+(i.durationMs??"")+"ms,cwd="+(i.cwd||"")+")":i.kind==="file"?m=(i.path||"")+" "+(i.change||"")+" "+(i.status||""):i.kind==="message"?m=(i.phase?"["+i.phase+"] ":"")+(i.text||""):i.kind==="reasoning"?m=i.summary||"":i.kind==="tool"?m=(i.server||"")+"/"+(i.tool||"")+" "+(i.status||""):i.kind==="call"?m=i.name||"":i.kind==="plan"?m=i.text||"":i.kind==="agent-start"?m="开始:"+(i.name||"")+(i.prompt?"("+i.prompt+")":""):i.kind==="agent-done"?m="结束:"+(i.name||"")+" "+(i.status||""):m=JSON.stringify(i).slice(0,300),"["+r+"] "+m}function Wy(){const[i,r]=v.useState(!!_l()),[m,o]=v.useState(_l()?"已保存到本浏览器(只用于调本站 API)":"未填 key,数据接口会返回 401"),[_,C]=v.useState("未加载"),[N,x]=v.useState("未加载"),[G,U]=v.useState("填 key 后判断权限…"),[Q,b]=v.useState(!1),[B,lt]=v.useState(""),[at,I]=v.useState(""),[V,dt]=v.useState([]),[Ot,te]=v.useState(""),[nt,Xt]=v.useState(""),[ee,ct]=v.useState([]),[yt,le]=v.useState(null),[de,Kt]=v.useState("未加载"),[Ft,Wt]=v.useState(""),[tl,mt]=v.useState([]),[Y,A]=v.useState(""),[et,Tt]=v.useState(""),[gt,ie]=v.useState([]),[Oe,ze]=v.useState([]),[y,R]=v.useState([]),[F,K]=v.useState("先选项目"),[pt,ht]=v.useState(""),[_t,k]=v.useState(""),[ut,ge]=v.useState(""),[Va,Ul]=v.useState(""),[Le,Gt]=v.useState([]),[zt,Re]=v.useState(""),[Fl,ae]=v.useState(""),[ha,El]=v.useState(""),[el,Ze]=v.useState(!1),[ne,qe]=v.useState(""),[ol,pe]=v.useState(""),[Hl,dl]=v.useState([]),[Bl,Ye]=v.useState(!1),Vt=v.useRef("");Vt.current=Ot;const ll=v.useRef("");ll.current=ol;const ml=v.useCallback(async()=>{try{const z=await tt($.health);x("backend="+z.backend+" db_ok="+z.db_ok+" worker_ok="+z.worker_ok+" commit="+String(z.commit||"").slice(0,7))}catch(z){x("加载失败:"+z.message)}},[]),ql=v.useCallback(async()=>{if(!_l()){C("未填 key,配额不显示");return}try{const z=await tt($.quotaMe),w=((z.used_usd_micros||0)/1e6).toFixed(2),W=z.quota_usd_micros===null||z.quota_usd_micros===void 0?"美元:本月用量 $"+w+"(不限额)":"美元:本月用量 $"+w+" / $"+((z.quota_usd_micros||0)/1e6).toFixed(2)+"(剩余 $"+((z.remaining_usd_micros||0)/1e6).toFixed(2)+")",qt=z.unpriced_token_cap===void 0||z.unpriced_tokens_used===void 0?"无价 token:未返回(旧服务端)":"无价 token:"+z.unpriced_tokens_used+" / "+z.unpriced_token_cap+" tokens";C(W+" | "+qt)}catch(z){C("配额加载失败:"+z.message)}},[]),La=v.useCallback(async()=>{if(!_l()){U("未填 key,管理区不可用"),b(!1);return}try{const z=await fetch($.adminQuotas,{headers:{"X-API-Key":_l()}});z.status===400?(U("已确认为全局管理员,管理操作可用"),b(!0)):z.status===403?(U("管理区仅全局管理员可用:当前 key 无全局管理员权限(服务端返回 403)"),b(!1)):z.status===401?(U("key 无效,管理区不可用(服务端返回 401)"),b(!1)):(U("管理权限判断失败(HTTP "+z.status+"),管理操作暂不可用"),b(!1))}catch(z){U("管理权限判断失败:"+z.message),b(!1)}},[]),$t=v.useCallback(async()=>{try{const w=(await tt($.projects)).projects||[];dt(w),Xt(w.length+" 个项目"),Vt.current&&w.some(W=>W.id===Vt.current)}catch(z){Xt("加载失败:"+z.message)}},[]),Wl=v.useCallback(async()=>{try{const z=await tt($.githubRepos);ct(z.repos||[])}catch{}},[]),yn=v.useCallback(async()=>{try{const z=await tt($.relayModels);dl(z.models||[]),Ye(!1)}catch{Ye(!0)}},[]),gn=v.useCallback(async()=>{try{const z=await tt($.workers);if(!Array.isArray(z)&&z.workers===void 0&&z.workers_total!==void 0){le(null),Kt(z.workers_total?"在线 "+z.workers_online+" / 离线 "+z.workers_offline+"(共 "+z.workers_total+";完整 worker 清单仅全局管理员可见)":"无 worker 注册"),Wt("");return}const w=Array.isArray(z)?z:z.workers||[];le(w),Kt(w.length?"":"无 worker 注册"),Wt("")}catch(z){Wt("加载失败:"+z.message)}},[]),Ke=v.useCallback(async z=>{const w=z!==void 0?z:Vt.current,W=ll.current;if(!w){Gt([]),Re(""),pe("");return}try{const Lt=(await tt($.environments(w))).environments||[];Gt(Lt),Re(Lt.length+" 个环境"),(W&&Lt.some(Ue=>Ue.id===W&&Ue.status==="ready")||W&&Lt.some(Ue=>Ue.id===W))&&pe(W);const xe=V.find(Ue=>Ue.id===w);xe&&xe.repo_url?(El("仓库:"+xe.repo_url),Ze(!1)):xe?(El("该项目未绑定仓库,环境无法创建——先选一个仓库保存"),Ze(!0)):(El(""),Ze(!1))}catch(qt){ae("加载失败:"+qt.message)}},[V]),Za=v.useCallback(async z=>{const w=z!==void 0?z:Vt.current;if(!w){mt([]);return}try{const W=await tt($.projectMembers(w));mt(W.members||[]),Tt("")}catch(W){Tt("成员加载失败:"+Oc(W))}},[]),va=v.useCallback(async z=>{const w=z!==void 0?z:Vt.current;if(!w){ie([]),ze([]),R([]),K("先选项目");return}K("");try{const W=await tt($.projectSkills(w));ie(W.skills||[])}catch(W){ht("技能加载失败:"+W.message)}try{const W=await tt($.projectApps(w));ze(W.apps||[])}catch(W){ht("应用加载失败:"+W.message)}try{const W=await tt($.projectMcp(w));R(W.servers||W.mcp_servers||[])}catch(W){ht("MCP 服务加载失败:"+W.message)}},[]),ou=v.useCallback(z=>{if(!z.trim()){o("key 为空,未保存");return}Zy(z.trim()),r(!0),o("已保存到本浏览器(只用于调本站 API)")},[]),du=v.useCallback(()=>{Ky(),r(!1),o("未填 key,数据接口会返回 401"),La()},[La]),$l=v.useCallback(async(z,w)=>{if(!z.trim()){Xt("项目名必填");return}const W={name:z.trim()};w.trim()&&(W.repo_url=w.trim());try{await tt($.projects,"POST",W),Xt("项目已建"),await $t()}catch(qt){Xt("新建失败:"+qt.message)}},[$t]),Se=v.useCallback(async(z,w,W)=>{const qt=Vt.current;if(!qt){ae("先选项目");return}if(!z.trim()){ae("环境名必填");return}const Lt={project_id:qt,name:z.trim()};w.trim()&&(Lt.branch=w.trim()),W&&(Lt.executor=W);try{await tt($.environmentsCreate,"POST",Lt),ae("环境已建,worker 准备中(creating → ready,失败会在列表里写原因)"),await Ke(qt)}catch(xe){ae("新建失败:"+xe.message)}},[Ke]),hl=v.useCallback(async z=>{if(window.confirm("确定归档该环境吗?归档后新任务不能再选它,进行中的任务不受影响(有进行中任务在用它时归档会被拒绝)。"))try{await tt($.environmentArchive(z),"POST",{}),await Ke()}catch(w){ae("归档失败:"+w.message)}},[Ke]),be=v.useCallback(async z=>{const w=Vt.current;if(!w){qe("先选项目");return}if(!z){qe("先选一个仓库");return}try{await tt($.project(w),"PATCH",{repo_url:z}),qe("仓库已保存,现在可以建环境了"),await $t(),await Ke(w)}catch(W){qe("保存失败:"+W.message)}},[$t,Ke]),H=v.useCallback(async(z,w)=>{const W=Vt.current;if(!W){A("先选项目");return}if(!z.trim()){A("请填成员 user_id 或用户名");return}try{await tt($.projectMembers(W),"POST",{user_id:z.trim(),role:w})}catch(qt){if(qt.message.includes("user not found"))try{await tt($.projectMembers(W),"POST",{username:z.trim(),role:w})}catch(Lt){A(Oc(Lt));return}else{A(Oc(qt));return}}A("已邀请成员"),await Za(W)},[Za]),D=v.useCallback(async(z,w)=>{const W=Vt.current;if(W)try{await tt($.projectMember(W,z),"PATCH",{role:w}),mt(qt=>qt.map(Lt=>Lt.user_id===z?{...Lt,role:w}:Lt)),A("角色已改为 "+w)}catch(qt){A(Oc(qt))}},[]),L=v.useCallback(async()=>{const z=Vt.current;if(!z){k("先选项目");return}try{await tt($.projectMcpReload(z),"POST",{}),k("配置已重载"),await va(z)}catch(w){k("重载失败:"+w.message)}},[va]),J=v.useCallback(async z=>{const w=Vt.current;if(!w){ge("先选项目");return}if(!z.trim()){ge("服务名不能为空");return}try{const W=await tt($.projectMcpOauth(w,z.trim()),"POST",{}),qt=W.url||W.auth_url||W.login_url||W.authorization_url||"",Lt=W.steps||W.instructions||"";let xe=`登录尚未完成:请在浏览器打开下面的链接或按步骤完成,完成后回到本页刷新 MCP 状态。 +`;qt&&(xe+=qt+` +`),Lt&&(xe+=(Array.isArray(Lt)?Lt.join(` `):String(Lt))+` -`),je+=JSON.stringify(W,null,2).slice(0,4e3),Ul(je),ge("已返回登录信息,见下方")}catch(W){ge("发起失败:"+W.message)}},[]),Ct=v.useCallback(async()=>{const z=at.trim();if(!z){lt("请填要查配额的用户 id");return}try{const w=await tt($.adminQuotaUser(z));lt("用户 "+z.slice(0,8)+":本月用量 "+rr(w.used_usd_micros)+" / 配额 "+rr(w.quota_usd_micros)+(w.remaining_usd_micros!==null&&w.remaining_usd_micros!==void 0?"(剩余 "+rr(w.remaining_usd_micros)+")":"")+" | 月份 "+(w.month||""))}catch(w){lt(fr(w))}},[at]),Nl=v.useCallback(async()=>{if(window.confirm("确定手动触发 sweep 吗?超阈值的陈旧 running 任务会被标为 interrupted。"))try{const w=(await tt($.adminSweep,"POST",{})).swept||[];lt("sweep 完成,清理 "+w.length+" 个任务"+(w.length?":"+w.join("、"):""))}catch(z){lt(fr(z))}},[]),De=v.useCallback(async()=>{try{const z=await tt($.adminBackup,"POST",{});lt("备份完成:backend="+z.backend+" | 路径 "+z.path+" | 大小 "+z.size_bytes+" 字节 | 任务 "+z.task_count+" 行")}catch(z){lt(fr(z))}},[]);return{keySaved:i,keyState:m,quotaText:_,healthText:N,adminGate:G,adminBody:Q,adminResult:B,adminUserId:at,setAdminUserId:I,projects:V,projectId:Ot,setProjectId:te,projectMsg:nt,githubRepos:ee,workers:yt,workersSummary:de,workersError:Ft,members:tl,memberMsg:Y,memberError:et,skills:gt,apps:Oe,mcpServers:y,skillMsg:F,skillError:pt,mcpMsg:_t,mcpOauthMsg:ut,mcpOauthBox:Va,envs:Le,envCount:zt,envMsg:Fl,envRepoLine:ha,envRepoBar:el,envRepoMsg:ne,envSelect:ol,setEnvSelect:pe,models:Hl,modelCustomVisible:Bl,refreshHealth:ml,loadQuota:ql,probeAdmin:La,refreshProjects:$t,loadGithubRepos:Wl,loadRelayModels:yn,refreshWorkers:gn,refreshEnvs:Ke,refreshMembers:Za,refreshSkills:va,saveKeyInput:ou,clearKeyInput:du,createProject:$l,createEnv:Se,archiveEnv:hl,saveEnvRepo:be,inviteMember:H,changeMemberRole:D,reloadMcp:L,mcpOauth:J,adminQuota:Ct,adminSweep:Nl,adminBackup:De}}function Jy(){const[i,r]=v.useState([]),[m,o]=v.useState(""),[_,C]=v.useState(""),[N,x]=v.useState(""),[G,U]=v.useState(""),Q=v.useCallback(async(at,I)=>{const V=at!==void 0?at:I;if(!V){r([]);return}try{const dt=await tt($.tasks(V));r(dt.tasks||[]),o("")}catch(dt){o("加载失败:"+dt.message)}},[]),b=v.useMemo(()=>{const at=G.trim().toLowerCase();return i.filter(I=>!(_&&I.status!==_||N&&(I.executor||"")!==N||at&&!((I.id||"")+" "+(I.prompt||"")).toLowerCase().includes(at)))},[i,_,N,G]),B=b.length+" 个任务(共 "+i.length+" 个)",lt=v.useCallback(async(at,I)=>{const V={...at};I.length&&(V.upload_id=await Ly(I));const dt=await tt($.tasksCreate,"POST",V);return"任务已建:"+Me(dt.id)},[]);return{tasks:i,taskError:m,statusFilter:_,setStatusFilter:C,executorFilter:N,setExecutorFilter:x,searchText:G,setSearchText:U,filteredTasks:b,taskCountText:B,refreshTasks:Q,dispatch:lt}}function Fy(i,r){const[m,o]=v.useState(null),[_,C]=v.useState(""),[N,x]=v.useState(""),[G,U]=v.useState(""),[Q,b]=v.useState(""),[B,lt]=v.useState(!1),[at,I]=v.useState(""),[V,dt]=v.useState([]),[Ot,te]=v.useState([]),[nt,Xt]=v.useState(""),[ee,ct]=v.useState([]),[yt,le]=v.useState(""),[de,Kt]=v.useState(""),[Ft,Wt]=v.useState([]),[tl,mt]=v.useState(""),[Y,A]=v.useState(""),[et,Tt]=v.useState(""),[gt,ie]=v.useState(""),[Oe,ze]=v.useState([]),[y,R]=v.useState([]),[F,K]=v.useState(""),[pt,ht]=v.useState([]),[_t,k]=v.useState(""),[ut,ge]=v.useState(""),[Va,Ul]=v.useState(""),[Le,Gt]=v.useState(""),[zt,Re]=v.useState([]),[Fl,ae]=v.useState(""),[ha,El]=v.useState(null),el=v.useRef(null),Ze=v.useRef(null),ne=v.useRef(null);ne.current=m;const qe=v.useCallback(()=>{if(el.current){try{el.current.abort()}catch{}el.current=null}Ze.current&&(clearTimeout(Ze.current),Ze.current=null)},[]),ol=v.useCallback(async H=>{try{const D=await tt($.taskAgents(H));te(D.agents||[]),Xt(D.note||"")}catch(D){te([]),Xt("子代理链路加载失败:"+D.message)}},[]),pe=v.useCallback(H=>{Ze.current&&clearTimeout(Ze.current),Ze.current=setTimeout(()=>void ol(H),1e3)},[ol]),Hl=v.useCallback(async H=>{if(!H.coordinator_parts){dt([]);return}try{const D=await tt($.tasksByParent(H.project_id||"",H.id));dt(D.tasks||[])}catch{dt([])}},[]),dl=v.useCallback(async H=>{try{const D=await tt($.taskFollowups(H));ze(D.followups||[])}catch{ze([])}},[]),Bl=v.useCallback(async H=>{try{const D=await tt($.taskChatHistory(H));El(D)}catch{El(null)}},[]),Ye=v.useCallback(async H=>{var L;const D=H||((L=ne.current)==null?void 0:L.id);if(D)try{const J=await tt($.taskReviews(D));ct(J.reviews||[]),Kt("")}catch(J){Kt("评审队列加载失败:"+J.message)}},[]),Vt=v.useCallback(async H=>{var L;const D=H||((L=ne.current)==null?void 0:L.id);if(D)try{const J=await tt($.taskApprovals(D));R(J.approvals||[])}catch(J){K("审批队列加载失败:"+J.message)}},[]),ll=v.useCallback(async H=>{try{const D=await tt($.taskMessages(H));ht(D.messages||[])}catch{ht([])}},[]),ml=v.useCallback(async H=>{try{const D=await tt($.taskThread(H)),L=D.thread||D;let J=L.turns;J==null&&(J=L.turn_count),J==null&&(J=L.turns_count),ge("id "+(L.id||H)+" | 名字 "+(L.name||L.thread_name||"")+" | 归档 "+(L.archived===void 0||L.archived===null?"":L.archived?"是":"否")+" | cwd "+(L.cwd||"")+(J!=null?" | turn 数 "+J:""))}catch(D){ge("线程加载失败:"+D.message)}},[]),ql=v.useCallback(async H=>{try{const D=await tt($.taskThreads(H));Re(D.threads||[])}catch{Re([])}},[]),La=v.useCallback(H=>{const D=["completed","failed","interrupted"].includes(H);Ul(D?"终态任务,线程操作可用":"仅终态任务可操作线程,当前状态 "+H+",按钮已置灰")},[]),$t=v.useCallback(async(H,D)=>{if(qe(),Wt([]),mt(""),A(""),su.includes(D)){try{const w=await tt($.taskTrace(H));Wt(w.entries||[]),mt(w.note||""),A(w.status||"")}catch(w){mt("链路加载失败:"+w.message)}return}const L=new AbortController;el.current=L;let J=[];const Ct={};let Nl="",De=!1,z="";try{const w={},W=_l();W&&(w["X-API-Key"]=W);const qt=await fetch($.taskTraceStream(H),{headers:w,signal:L.signal});if(!qt.ok){let ya="HTTP "+qt.status;try{const Il=await qt.json();Il&&Il.error&&(ya=Il.error)}catch{}throw qt.status===401&&(ya+="(key 未填或无效)"),new Error(ya)}const Lt=qt.body.getReader(),je=new TextDecoder;let Ue="";for(;;){const ya=await Lt.read();if(ya.done)break;Ue+=je.decode(ya.value,{stream:!0});const Il=Ue.split(` +`),xe+=JSON.stringify(W,null,2).slice(0,4e3),Ul(xe),ge("已返回登录信息,见下方")}catch(W){ge("发起失败:"+W.message)}},[]),Ct=v.useCallback(async()=>{const z=at.trim();if(!z){lt("请填要查配额的用户 id");return}try{const w=await tt($.adminQuotaUser(z));lt("用户 "+z.slice(0,8)+":本月用量 "+rr(w.used_usd_micros)+" / 配额 "+rr(w.quota_usd_micros)+(w.remaining_usd_micros!==null&&w.remaining_usd_micros!==void 0?"(剩余 "+rr(w.remaining_usd_micros)+")":"")+" | 月份 "+(w.month||""))}catch(w){lt(fr(w))}},[at]),Nl=v.useCallback(async()=>{if(window.confirm("确定手动触发 sweep 吗?超阈值的陈旧 running 任务会被标为 interrupted。"))try{const w=(await tt($.adminSweep,"POST",{})).swept||[];lt("sweep 完成,清理 "+w.length+" 个任务"+(w.length?":"+w.join("、"):""))}catch(z){lt(fr(z))}},[]),De=v.useCallback(async()=>{try{const z=await tt($.adminBackup,"POST",{});lt("备份完成:backend="+z.backend+" | 路径 "+z.path+" | 大小 "+z.size_bytes+" 字节 | 任务 "+z.task_count+" 行")}catch(z){lt(fr(z))}},[]);return{keySaved:i,keyState:m,quotaText:_,healthText:N,adminGate:G,adminBody:Q,adminResult:B,adminUserId:at,setAdminUserId:I,projects:V,projectId:Ot,setProjectId:te,projectMsg:nt,githubRepos:ee,workers:yt,workersSummary:de,workersError:Ft,members:tl,memberMsg:Y,memberError:et,skills:gt,apps:Oe,mcpServers:y,skillMsg:F,skillError:pt,mcpMsg:_t,mcpOauthMsg:ut,mcpOauthBox:Va,envs:Le,envCount:zt,envMsg:Fl,envRepoLine:ha,envRepoBar:el,envRepoMsg:ne,envSelect:ol,setEnvSelect:pe,models:Hl,modelCustomVisible:Bl,refreshHealth:ml,loadQuota:ql,probeAdmin:La,refreshProjects:$t,loadGithubRepos:Wl,loadRelayModels:yn,refreshWorkers:gn,refreshEnvs:Ke,refreshMembers:Za,refreshSkills:va,saveKeyInput:ou,clearKeyInput:du,createProject:$l,createEnv:Se,archiveEnv:hl,saveEnvRepo:be,inviteMember:H,changeMemberRole:D,reloadMcp:L,mcpOauth:J,adminQuota:Ct,adminSweep:Nl,adminBackup:De}}function $y(){const[i,r]=v.useState([]),[m,o]=v.useState(""),[_,C]=v.useState(""),[N,x]=v.useState(""),[G,U]=v.useState(""),Q=v.useCallback(async(at,I)=>{const V=at!==void 0?at:I;if(!V){r([]);return}try{const dt=await tt($.tasks(V));r(dt.tasks||[]),o("")}catch(dt){o("加载失败:"+dt.message)}},[]),b=v.useMemo(()=>{const at=G.trim().toLowerCase();return i.filter(I=>!(_&&I.status!==_||N&&(I.executor||"")!==N||at&&!((I.id||"")+" "+(I.prompt||"")).toLowerCase().includes(at)))},[i,_,N,G]),B=b.length+" 个任务(共 "+i.length+" 个)",lt=v.useCallback(async(at,I)=>{const V={...at};I.length&&(V.upload_id=await Jy(I));const dt=await tt($.tasksCreate,"POST",V);return"任务已建:"+Me(dt.id)},[]);return{tasks:i,taskError:m,statusFilter:_,setStatusFilter:C,executorFilter:N,setExecutorFilter:x,searchText:G,setSearchText:U,filteredTasks:b,taskCountText:B,refreshTasks:Q,dispatch:lt}}function Iy(i,r){const[m,o]=v.useState(null),[_,C]=v.useState(""),[N,x]=v.useState(""),[G,U]=v.useState(""),[Q,b]=v.useState(""),[B,lt]=v.useState(!1),[at,I]=v.useState(""),[V,dt]=v.useState([]),[Ot,te]=v.useState([]),[nt,Xt]=v.useState(""),[ee,ct]=v.useState([]),[yt,le]=v.useState(""),[de,Kt]=v.useState(""),[Ft,Wt]=v.useState([]),[tl,mt]=v.useState(""),[Y,A]=v.useState(""),[et,Tt]=v.useState(""),[gt,ie]=v.useState(""),[Oe,ze]=v.useState([]),[y,R]=v.useState([]),[F,K]=v.useState(""),[pt,ht]=v.useState([]),[_t,k]=v.useState(""),[ut,ge]=v.useState(""),[Va,Ul]=v.useState(""),[Le,Gt]=v.useState(""),[zt,Re]=v.useState([]),[Fl,ae]=v.useState(""),[ha,El]=v.useState(null),el=v.useRef(null),Ze=v.useRef(null),ne=v.useRef(null);ne.current=m;const qe=v.useCallback(()=>{if(el.current){try{el.current.abort()}catch{}el.current=null}Ze.current&&(clearTimeout(Ze.current),Ze.current=null)},[]),ol=v.useCallback(async H=>{try{const D=await tt($.taskAgents(H));te(D.agents||[]),Xt(D.note||"")}catch(D){te([]),Xt("子代理链路加载失败:"+D.message)}},[]),pe=v.useCallback(H=>{Ze.current&&clearTimeout(Ze.current),Ze.current=setTimeout(()=>void ol(H),1e3)},[ol]),Hl=v.useCallback(async H=>{if(!H.coordinator_parts){dt([]);return}try{const D=await tt($.tasksByParent(H.project_id||"",H.id));dt(D.tasks||[])}catch{dt([])}},[]),dl=v.useCallback(async H=>{try{const D=await tt($.taskFollowups(H));ze(D.followups||[])}catch{ze([])}},[]),Bl=v.useCallback(async H=>{try{const D=await tt($.taskChatHistory(H));El(D)}catch{El(null)}},[]),Ye=v.useCallback(async H=>{var L;const D=H||((L=ne.current)==null?void 0:L.id);if(D)try{const J=await tt($.taskReviews(D));ct(J.reviews||[]),Kt("")}catch(J){Kt("评审队列加载失败:"+J.message)}},[]),Vt=v.useCallback(async H=>{var L;const D=H||((L=ne.current)==null?void 0:L.id);if(D)try{const J=await tt($.taskApprovals(D));R(J.approvals||[])}catch(J){K("审批队列加载失败:"+J.message)}},[]),ll=v.useCallback(async H=>{try{const D=await tt($.taskMessages(H));ht(D.messages||[])}catch{ht([])}},[]),ml=v.useCallback(async H=>{try{const D=await tt($.taskThread(H)),L=D.thread||D;let J=L.turns;J==null&&(J=L.turn_count),J==null&&(J=L.turns_count),ge("id "+(L.id||H)+" | 名字 "+(L.name||L.thread_name||"")+" | 归档 "+(L.archived===void 0||L.archived===null?"":L.archived?"是":"否")+" | cwd "+(L.cwd||"")+(J!=null?" | turn 数 "+J:""))}catch(D){ge("线程加载失败:"+D.message)}},[]),ql=v.useCallback(async H=>{try{const D=await tt($.taskThreads(H));Re(D.threads||[])}catch{Re([])}},[]),La=v.useCallback(H=>{const D=["completed","failed","interrupted"].includes(H);Ul(D?"终态任务,线程操作可用":"仅终态任务可操作线程,当前状态 "+H+",按钮已置灰")},[]),$t=v.useCallback(async(H,D)=>{if(qe(),Wt([]),mt(""),A(""),su.includes(D)){try{const w=await tt($.taskTrace(H));Wt(w.entries||[]),mt(w.note||""),A(w.status||"")}catch(w){mt("链路加载失败:"+w.message)}return}const L=new AbortController;el.current=L;let J=[];const Ct={};let Nl="",De=!1,z="";try{const w={},W=_l();W&&(w["X-API-Key"]=W);const qt=await fetch($.taskTraceStream(H),{headers:w,signal:L.signal});if(!qt.ok){let ya="HTTP "+qt.status;try{const Il=await qt.json();Il&&Il.error&&(ya=Il.error)}catch{}throw qt.status===401&&(ya+="(key 未填或无效)"),new Error(ya)}const Lt=qt.body.getReader(),xe=new TextDecoder;let Ue="";for(;;){const ya=await Lt.read();if(ya.done)break;Ue+=xe.decode(ya.value,{stream:!0});const Il=Ue.split(` `);Ue=Il.pop()||"";for(const ii of Il){const mu=ii.split(` `).filter(we=>we.indexOf("data: ")===0).map(we=>we.slice(6)).join(` @@ -68,7 +68,7 @@ Error generating stack: `+a.message+` `+D.result_text.slice(0,8e3)+` `),D.error_text&&(L+=`=== error === `+D.error_text.slice(0,8e3)+` -`),C(L||"(暂无 result/error 输出)")}catch{}dl(H.id),Bl(H.id),Ye(H.id),Vt(H.id),Hl(H),ol(H.id),ll(H.id),ml(H.id),ql(H.id)}},[dl,Bl,Ye,Vt,Hl,ol,ll,ml,ql]),gn=v.useCallback(async H=>{const D=ne.current;if(!D)return;const L={cancel:"确定取消该任务吗?",merge:"确定把 completed 任务标为 merged 吗?",pr:"确定为该任务提 PR 吗?(会在仓库真实建 PR)"};if(!(L[H]&&!window.confirm(L[H])))try{const J=await tt($.taskAction(D.id,H),"POST",{});x(H+" 已提交:"+JSON.stringify(J).slice(0,300)),r(),await Wl(D.id)}catch(J){x(H+" 失败:"+J.message)}},[Wl,r]),Ke=v.useCallback(async()=>{const H=ne.current;if(H)try{const D=await tt($.taskCost(H.id));b(JSON.stringify(D,null,2).slice(0,4e3))}catch(D){b("查成本失败:"+D.message)}},[]),Za=v.useCallback(async H=>{const D=ne.current;if(D){if(!H.trim()){I("分支消息必填");return}if(!su.includes(D.status)){I("仅终态任务可分支");return}try{const L=await tt($.taskFork(D.id),"POST",{message:H.trim()});I("分支任务已建:"+L.id.slice(0,8)),r()}catch(L){I("分支失败:"+L.message)}}},[r]),va=v.useCallback(async H=>{const D=ne.current;if(D)try{await tt($.taskReviews(D.id),"POST",H),le("评审已登记(requested)"),await Ye(D.id)}catch(L){le("登记评审需求失败:"+L.message)}},[Ye]),ou=v.useCallback(H=>{const D=ne.current;if(!D)return;const L=window.prompt("输入该条评审的 findings(将写回记录并标为 completed):");L!==null&&tt($.taskReviewFindings(D.id,H),"POST",{findings:L}).then(()=>void Ye(D.id)).catch(J=>le("写 findings 失败:"+J.message))},[Ye]),du=v.useCallback((H,D)=>{const L=ne.current;if(!L)return;const J=D==="approved"?"approve":"deny";tt($.taskApprovalDecision(L.id,H,J),"POST",{}).then(()=>{K("已记录"+(D==="approved"?"允许":"拒绝")+"(当前版本只留回执,不拦截实时行为)"),Vt(L.id)}).catch(Ct=>K("决定失败:"+Ct.message))},[Vt]),$l=v.useCallback(async(H,D,L)=>{const J=ne.current;if(J){if(!D.trim()){k("目标任务 id 不能为空");return}if(!L.trim()){k("消息正文不能为空");return}try{const Ct=await tt($.taskMessagesTo(D.trim()),"POST",{from_task_id:J.id,body:L.trim(),mode:H});k("已发送("+Ct.delivery+")"),await ll(J.id)}catch(Ct){k("发送失败:"+Ct.message)}}},[ll]),Se=v.useCallback((H,D)=>{const L=ne.current;if(!L)return;if(!["completed","failed","interrupted"].includes(L.status)){Gt("仅 completed/failed/interrupted 任务可操作线程(merged/merge-failed 不可改,服务端同样 409)");return}const J={};if(H==="rename"){if(!D.trim()){Gt("新线程名不能为空");return}J.name=D.trim()}tt($.taskThreadAction(L.id,H),"POST",J).then(Ct=>{Gt(H+" 已提交:"+JSON.stringify(Ct).slice(0,300)),ml(L.id),ql(L.id)}).catch(Ct=>Gt(H+" 失败:"+Ct.message))},[ml,ql]),hl=v.useCallback(async H=>{const D=ne.current;if(!D)return;const L=H.trim();if(!L){ae("消息不能为空");return}try{su.includes(D.status)&&D.status!=="merged"?(await tt($.taskContinue(D.id),"POST",{message:L}),ae("已重新排队,同一会话继续"),r(),await Wl(D.id)):["queued","running"].includes(D.status)?(await tt($.taskFollowups(D.id),"POST",{body:L,mode:"direct"}),ae("已直接发送"),await dl(D.id),await Bl(D.id)):ae("merged/merge-failed 任务不可继续,也不可发后续消息")}catch(J){ae("发送失败:"+J.message)}},[Wl,r,dl,Bl]),be=v.useCallback(async()=>{const H=ne.current;if(!H){ie("先选一个任务");return}try{const D=await tt($.taskTrace(H.id)),L=new Blob([JSON.stringify({task_id:H.id,status:D.status,note:D.note||"",count:(D.entries||[]).length,entries:D.entries||[]},null,2)],{type:"application/json"}),J=document.createElement("a");J.href=URL.createObjectURL(L),J.download="trace-"+H.id.slice(0,8)+".json",document.body.appendChild(J),J.click(),J.remove(),setTimeout(()=>URL.revokeObjectURL(J.href),1e3),ie("已下载完整链路 "+(D.entries||[]).length+" 条")}catch(D){ie("下载失败:"+D.message)}},[]);return v.useEffect(()=>()=>qe(),[qe]),{currentTask:m,detailBody:_,actionMsg:N,actionReasons:G,costBox:Q,forkVisible:B,setForkVisible:lt,forkMsg:at,coordChildren:V,agents:Ot,agentsNote:nt,reviews:ee,reviewMsg:yt,reviewError:de,traceEntries:Ft,traceNote:tl,traceDone:Y,traceKind:et,setTraceKind:Tt,traceMsg:gt,followups:Oe,approvals:y,approvalMsg:F,peerMessages:pt,peerMsg:_t,threadText:ut,threadGateNote:Va,threadMsg:Le,threadList:zt,chatMsg:Fl,chatHistory:ha,showDetail:Wl,refreshDetailLists:yn,doAction:gn,taskCost:Ke,forkTask:Za,postReview:va,submitFindings:ou,decideApproval:du,postPeer:$l,threadAction:Se,sendChatMessage:hl,downloadTrace:be,refreshReviews:()=>void Ye(),refreshApprovals:()=>void Vt()}}function Wy(i){const[r,m]=v.useState([]),[o,_]=v.useState(""),[C,N]=v.useState(null),[x,G]=v.useState(""),U=v.useCallback(async lt=>{const at=lt!==void 0?lt:i();if(!at){m([]);return}try{const I=await tt($.projectAutomations(at));m(I.automations||[])}catch(I){_("自动化加载失败:"+I.message)}},[i]),Q=v.useCallback(async(lt,at,I,V)=>{const dt=i();if(!dt){_("先选项目");return}if(!lt.trim()){_("自动化名称必填");return}if(!at.trim()){_("定时任务内容必填");return}const Ot={name:lt.trim(),prompt:at.trim()};I.trim()&&(Ot.interval_seconds=parseInt(I.trim(),10)),V.trim()&&(Ot.repo_url=V.trim());try{await tt($.projectAutomations(dt),"POST",Ot),_("自动化已创建(登记定义,到期后由执行器认领)"),await U(dt)}catch(te){_("创建失败:"+te.message)}},[i,U]),b=v.useCallback(lt=>{const at=i();at&&tt($.projectAutomationCancel(at,lt),"POST",{}).then(()=>{_("自动化已取消"),U(at)}).catch(I=>_("取消失败:"+I.message))},[i,U]),B=v.useCallback(async lt=>{const at=lt!==void 0?lt:i();if(!at){N(null);return}try{const I=await tt($.projectTriage(at));N(I),G("")}catch(I){G("分诊加载失败:"+I.message)}},[i]);return{automations:r,autoMsg:o,triage:C,triageError:x,refreshAutomations:U,createAutomation:Q,cancelAutomation:b,refreshTriage:B}}function $y(i,r){const m=v.useRef(i);m.current=i,v.useEffect(()=>{const o=setInterval(()=>{const _=document.activeElement;m.current(_?_.tagName==="SELECT":!1)},r);return()=>clearInterval(o)},[r])}function Iy(i,r){const m=v.useRef(i);m.current=i,v.useEffect(()=>{const o=setInterval(()=>m.current(),r);return()=>clearInterval(o)},[r])}function Py(i){const r=m=>String(m).padStart(2,"0");return r(i.getHours())+":"+r(i.getMinutes())+":"+r(i.getSeconds())}function tg(){var I;const i=Ky(),r=Jy(),m=v.useRef("");m.current=i.projectId;const o=v.useCallback(()=>m.current,[]),_=Wy(o),C=v.useCallback(V=>{const dt=i.projects.find(Ot=>Ot.id===V);return dt&&dt.my_role||null},[i.projects]),N=v.useCallback(()=>{r.refreshTasks(void 0,m.current)},[r]),x=Fy(C,N),[G,U]=v.useState("--:--:--"),Q=v.useCallback(V=>{i.setProjectId(V),m.current=V,r.refreshTasks(V),i.refreshEnvs(V),i.refreshMembers(V),i.refreshSkills(V),_.refreshAutomations(V),_.refreshTriage(V)},[i,r,_]),b=(I=i.projects[0])==null?void 0:I.id;v.useEffect(()=>{!i.projectId&&b&&Q(b)},[i.projectId,b,Q]);const B=v.useCallback(V=>{i.saveKeyInput(V),V.trim()&&(i.refreshHealth(),i.refreshProjects(),i.refreshWorkers(),m.current&&(r.refreshTasks(m.current),i.refreshEnvs(m.current),i.refreshMembers(m.current)),i.loadRelayModels(),i.loadQuota(),i.loadGithubRepos(),i.probeAdmin())},[i,r]),lt=v.useCallback(V=>{if(U(Py(new Date)),!_l()){i.refreshHealth();return}r.refreshTasks(void 0,m.current),i.refreshHealth(),i.loadQuota(),i.refreshWorkers(),i.refreshMembers(),i.refreshSkills(),_.refreshAutomations(),_.refreshTriage(),x.refreshDetailLists(),V||(i.refreshProjects(),i.refreshEnvs())},[i,r,_,x]),at=v.useCallback(()=>{_l()&&(i.loadRelayModels(),i.loadGithubRepos())},[i]);return v.useEffect(()=>{i.refreshHealth(),i.refreshProjects(),i.refreshWorkers(),i.loadQuota(),i.loadGithubRepos(),_l()&&i.loadRelayModels(),i.probeAdmin()},[]),{keySaved:i.keySaved,keyState:i.keyState,saveKeyInput:B,clearKeyInput:i.clearKeyInput,quotaText:i.quotaText,healthText:i.healthText,refreshHealth:i.refreshHealth,adminGate:i.adminGate,adminBody:i.adminBody,adminResult:i.adminResult,adminUserId:i.adminUserId,setAdminUserId:i.setAdminUserId,adminQuota:i.adminQuota,adminSweep:i.adminSweep,adminBackup:i.adminBackup,projects:i.projects,projectId:i.projectId,projectMsg:i.projectMsg,selectProject:Q,refreshProjects:i.refreshProjects,createProject:i.createProject,githubRepos:i.githubRepos,workers:i.workers,workersSummary:i.workersSummary,workersError:i.workersError,refreshWorkers:i.refreshWorkers,members:i.members,memberMsg:i.memberMsg,memberError:i.memberError,refreshMembers:()=>void i.refreshMembers(),inviteMember:i.inviteMember,changeMemberRole:i.changeMemberRole,skills:i.skills,apps:i.apps,mcpServers:i.mcpServers,skillMsg:i.skillMsg,skillError:i.skillError,mcpMsg:i.mcpMsg,mcpOauthMsg:i.mcpOauthMsg,mcpOauthBox:i.mcpOauthBox,refreshSkills:()=>void i.refreshSkills(),reloadMcp:i.reloadMcp,mcpOauth:i.mcpOauth,envs:i.envs,envCount:i.envCount,envMsg:i.envMsg,envRepoLine:i.envRepoLine,envRepoBar:i.envRepoBar,envRepoMsg:i.envRepoMsg,envSelect:i.envSelect,setEnvSelect:i.setEnvSelect,refreshEnvs:()=>void i.refreshEnvs(),createEnv:i.createEnv,archiveEnv:i.archiveEnv,saveEnvRepo:i.saveEnvRepo,models:i.models,modelCustomVisible:i.modelCustomVisible,tasks:r.tasks,taskCountText:r.taskCountText,taskError:r.taskError,refreshTasks:()=>void r.refreshTasks(void 0,m.current),statusFilter:r.statusFilter,setStatusFilter:r.setStatusFilter,executorFilter:r.executorFilter,setExecutorFilter:r.setExecutorFilter,searchText:r.searchText,setSearchText:r.setSearchText,filteredTasks:r.filteredTasks,currentTask:x.currentTask,detailBody:x.detailBody,actionMsg:x.actionMsg,actionReasons:x.actionReasons,showDetail:V=>void x.showDetail(V),doAction:x.doAction,taskCost:x.taskCost,costBox:x.costBox,forkVisible:x.forkVisible,setForkVisible:x.setForkVisible,forkTask:x.forkTask,forkMsg:x.forkMsg,coordChildren:x.coordChildren,coordText:"",agents:x.agents,agentsNote:x.agentsNote,reviews:x.reviews,reviewMsg:x.reviewMsg,reviewError:x.reviewError,refreshReviews:x.refreshReviews,postReview:x.postReview,submitFindings:x.submitFindings,traceEntries:x.traceEntries,traceNote:x.traceNote,traceDone:x.traceDone,traceKind:x.traceKind,setTraceKind:x.setTraceKind,downloadTrace:x.downloadTrace,traceMsg:x.traceMsg,sendChatMessage:x.sendChatMessage,chatMsg:x.chatMsg,chatHistory:x.chatHistory,followups:x.followups,approvals:x.approvals,approvalMsg:x.approvalMsg,refreshApprovals:x.refreshApprovals,decideApproval:x.decideApproval,peerMessages:x.peerMessages,peerMsg:x.peerMsg,postPeer:x.postPeer,automations:_.automations,autoMsg:_.autoMsg,refreshAutomations:()=>void _.refreshAutomations(),createAutomation:_.createAutomation,cancelAutomation:_.cancelAutomation,triage:_.triage,triageError:_.triageError,refreshTriage:()=>void _.refreshTriage(),threadText:x.threadText,threadGateNote:x.threadGateNote,threadMsg:x.threadMsg,threadList:x.threadList,threadAction:x.threadAction,dispatch:async(V,dt)=>{const Ot=await r.dispatch(V,dt);return r.refreshTasks(m.current),Ot},dispatchMsg:"",refreshAll:lt,refreshSlow:at,refreshStamp:G}}function cu({label:i,value:r,sub:m}){return s.jsxs("div",{className:"dash-card data-card",children:[s.jsx("div",{className:"dash-card-label",children:i}),s.jsx("div",{className:"dash-card-value",children:r}),s.jsx("div",{className:"muted",children:m})]})}function eg(){const i=Mt(),r=i.healthText==="未加载"?"未加载":i.healthText.includes("worker_ok=true")?"正常":i.healthText.includes("worker_ok=false")?"异常":i.healthText.includes("加载失败")?"加载失败":"未知",m=i.quotaText.match(/剩余 \$([0-9.]+)/),o=i.quotaText.includes("加载失败")?"加载失败":i.quotaText.includes("未填 key")||i.quotaText==="未加载"?"未加载":m?"$"+m[1]:"配额",_=["running","completed","failed","queued","merged","interrupted"].map(b=>i.tasks.filter(B=>B.status===b).length).map((b,B)=>["running","completed","failed","queued","merged","interrupted"][B]+" "+b).join(" | "),C=i.projects.find(b=>b.id===i.projectId),N=i.taskError?{value:"加载失败",sub:i.taskError}:i.projectId?{value:String(i.tasks.length),sub:i.taskCountText+" | "+_+(C?" | "+C.name:"")}:{value:"先选项目",sub:i.projectMsg||"项目加载后自动选第一个"};let x;if(i.workersError)x={value:"加载失败",sub:i.workersError};else if(i.workers===null)x={value:i.workersSummary||"未加载",sub:"完整 worker 清单仅全局管理员可见"};else{const b=i.workers.filter(B=>{if(B.alive!==void 0&&B.alive!==null)return!!B.alive;const lt=Qh(B).age;return lt!==null&<<=120}).length;x={value:b+" 在线 / "+i.workers.length,sub:i.workers.length-b+" 离线"}}const G=i.projectMsg.includes("加载失败")?{value:"加载失败",sub:i.projectMsg}:{value:i.projects.length+" 个",sub:C?"当前项目:"+C.name:"未选项目(加载后自动选第一个)"},U=[i.envMsg,i.memberError,i.skillError].filter(b=>b&&b.includes("失败")),Q=i.projectId?U.length?{value:"部分加载失败",sub:U.join(" | ")}:{value:i.envs.length+" 个环境",sub:i.members.length+" 成员 | "+i.skills.length+" 技能 | "+i.apps.length+" 应用 | "+i.mcpServers.length+" MCP"}:{value:"先选项目",sub:"选项目后显示环境 / 成员 / 技能计数"};return s.jsxs("section",{className:"dash-cards","aria-label":"数据卡片",children:[s.jsx(cu,{label:"健康",value:r,sub:i.healthText}),s.jsx(cu,{label:"配额",value:o,sub:i.quotaText}),s.jsx(cu,{label:"任务",value:N.value,sub:N.sub}),s.jsx(cu,{label:"Workers",value:x.value,sub:x.sub}),s.jsx(cu,{label:"项目",value:G.value,sub:G.sub}),s.jsx(cu,{label:"项目数据",value:Q.value,sub:Q.sub})]})}function Ve({id:i,className:r,title:m,children:o}){return s.jsxs("section",{id:i,className:"card"+(r?" "+r:""),children:[m?s.jsx("h2",{children:m}):null,o]})}function Dt({children:i}){return s.jsx("div",{className:"bar",children:i})}function Dl({items:i,empty:r}){return i.length?s.jsx("ul",{className:"data-list",children:i.map((m,o)=>s.jsx("li",{children:m},o))}):s.jsx("div",{className:"muted",children:r||"(暂无)"})}function ru({children:i}){return s.jsx("ul",{className:"data-list",children:i})}function lg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState(!1),[x,G]=v.useState(!1),[U,Q]=v.useState(!1),[b,B]=v.useState("docker"),[lt,at]=v.useState(""),[I,V]=v.useState(""),[dt,Ot]=v.useState(""),[te,nt]=v.useState(""),[Xt,ee]=v.useState(""),[ct,yt]=v.useState(""),[le,de]=v.useState(""),Kt=v.useRef(null),Ft=v.useRef(null),Wt=v.useRef(null),[tl,mt]=v.useState("");async function Y(){var Oe,ze,y;if(mt(""),!i.projectId){mt("先选项目");return}if(!r.trim()){mt("prompt 必填");return}const A={project_id:i.projectId,prompt:r.trim()};i.envSelect&&(A.environment_id=i.envSelect),b&&(A.executor=b);const et=I.trim()||lt;et&&(A.model=et),dt&&(A.effort=dt);const Tt=ct.trim()||Xt;if(Tt&&(A.child_model=Tt),le&&(A.child_effort=le),te&&(A.approval=te),U){if(te==="full"){mt("计划模式不能与完全访问同用");return}if(C||x){mt("计划模式不能与 goal 模式同用");return}A.plan=1}x?(A.goal_mode=1,A.no_time_limit=1):C&&(A.goal_mode=1);const gt=o.trim();if(gt){try{A.coordinator_parts=JSON.parse(gt)}catch{mt("协调员子任务 JSON 解析失败");return}if(!Array.isArray(A.coordinator_parts)){mt("协调员子任务必须是数组");return}if(C||x||U){mt("协调员任务不能与 goal/计划模式同用:协调员任务本身不跑模型回合,请取消 goal/计划勾选,或清空协调员 JSON");return}}const ie=Zy(((Oe=Kt.current)==null?void 0:Oe.files)||null,((ze=Ft.current)==null?void 0:ze.files)||null,((y=Wt.current)==null?void 0:y.files)||null);try{const R=await i.dispatch(A,ie);mt(R),m(""),_(""),Kt.current&&(Kt.current.value=""),Ft.current&&(Ft.current.value=""),Wt.current&&(Wt.current.value="")}catch(R){mt("提交失败:"+((R==null?void 0:R.message)||String(R)))}}return s.jsxs(Ve,{id:"nav-newtask",className:"composer",title:"新建任务",children:[s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"环境",value:i.envSelect,onChange:A=>i.setEnvSelect(A.target.value),children:[s.jsx("option",{value:"",children:"环境:不指定(走项目仓库)"}),i.envs.map(A=>s.jsxs("option",{value:A.id,disabled:A.status!=="ready",children:[A.name,"(",A.status,")"]},A.id))]}),s.jsxs("select",{"aria-label":"执行器",value:b,onChange:A=>B(A.target.value),children:[s.jsx("option",{value:"docker",children:"docker(默认,多用户下隔离最强)"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"cloud",children:"cloud"})]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:C,onChange:A=>N(A.target.checked)})," goal 模式"]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:x,onChange:A=>G(A.target.checked)})," goal 模式无敌版"]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:U,onChange:A=>Q(A.target.checked)})," 计划模式(只读)"]})]}),s.jsx("textarea",{className:"prompt stacked",placeholder:"任务 prompt(必填)",value:r,onChange:A=>m(A.target.value)}),s.jsx("textarea",{className:"coord stacked",placeholder:"协调员子任务 JSON(可选),留空为普通任务",value:o,onChange:A=>_(A.target.value)}),s.jsxs("div",{className:"muted",children:["协调员格式:[","{",'"name":"后端","prompt":"做后端"',"}",",","{",'"name":"前端","prompt":"做前端"',"}","];提交后 worker 并行建子任务、等齐、合流汇总。不能与 goal/计划模式同用。协调员与 goal/计划互斥:勾了 goal 或计划模式时不要填协调员 JSON,提交前会校验并拦截。子任务费用记父任务创建人账;父任务创建时按分工数预留配额,余额不足时整个父任务被挡下。"]}),s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"模型",value:lt,onChange:A=>at(A.target.value),children:[s.jsx("option",{value:"",children:"模型:默认(跟随配置)"}),i.models.map(A=>s.jsx("option",{value:A,children:A},A))]}),i.modelCustomVisible?s.jsx("input",{type:"text",placeholder:"手动输入模型(中转列表取不到时用)",value:I,onChange:A=>V(A.target.value)}):null,s.jsxs("select",{"aria-label":"推理强度",value:dt,onChange:A=>Ot(A.target.value),children:[s.jsx("option",{value:"",children:"推理强度:默认(跟随配置)"}),Yh.map(A=>s.jsx("option",{value:A,children:A},A))]}),s.jsxs("select",{"aria-label":"权限",value:te,onChange:A=>nt(A.target.value),children:[s.jsx("option",{value:"",children:"权限:默认(跟随配置)"}),s.jsx("option",{value:"ask",children:"请求批准"}),s.jsx("option",{value:"auto",children:"帮我批准"}),s.jsx("option",{value:"full",children:"完全访问"})]})]}),s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"子任务模型",value:Xt,onChange:A=>ee(A.target.value),children:[s.jsx("option",{value:"",children:"子任务模型:跟随本任务模型"}),i.models.map(A=>s.jsx("option",{value:A,children:A},A))]}),s.jsx("input",{type:"text",placeholder:"子任务模型手动输入(中转列表里没有时填,如 gpt-6-luna;留空=跟随本任务模型)",value:ct,onChange:A=>yt(A.target.value)}),s.jsxs("select",{"aria-label":"子任务强度",value:le,onChange:A=>de(A.target.value),children:[s.jsx("option",{value:"",children:"子任务强度:跟随本任务强度"}),Yh.map(A=>s.jsx("option",{value:A,children:A},A))]})]}),s.jsx("div",{className:"muted",children:"子任务模型/强度是派生默认:本任务用 marker task-create 或协调员分工派生的子任务,未显式写模型/强度时用它;块/分工里显式写了则覆盖它。也可以不在这里填、直接在 prompt 里写“子任务用 gpt-6-luna max”,建任务时服务端会解析成同一对字段(任务详情里可核对)。"}),C?s.jsx("div",{className:"muted",children:"goal 模式:输入框内容即目标,不需要专用 prompt 与验收命令;不限轮次,模型确认达成后在回复末尾输出“目标已达成”即结束,未达成会一直运行,可用取消停止。"}):null,x?s.jsx("div",{className:"muted",children:"goal 模式无敌版:goal 模式 + 任务不限时(去掉 worker/docker 总超时;单轮 600 秒护栏还在,不限的是任务总时长与总轮次)。服务端默认的自动续跑与断点镜像同时生效。"}):null,s.jsxs(Dt,{children:[s.jsx("span",{className:"muted",children:"附件(放进任务工作区,图片与普通文件不区分):"}),s.jsx("input",{ref:Kt,type:"file",multiple:!0,title:"文件"}),s.jsx("input",{ref:Ft,type:"file",multiple:!0,title:"文件夹",webkitdirectory:""}),s.jsx("input",{ref:Wt,type:"file",accept:"image/*",multiple:!0,title:"图片"})]}),s.jsxs(Dt,{children:[s.jsx("button",{className:"seal",onClick:Y,children:"提交任务"}),s.jsx("span",{className:"muted",children:tl||i.dispatchMsg})]})]})}function ag(i){const r=(i.prompt||"").trim();return r?[...r][0]:i.id?[...i.id][0]:"?"}function zc(i){const r=Math.max(0,Math.floor(i));if(r<60)return r+"秒";if(r<3600){const _=Math.floor(r/60),C=r%60;return C?_+"分"+C+"秒":_+"分"}if(r<86400){const _=Math.floor(r/3600),C=Math.floor(r%3600/60);return C?_+"小时"+C+"分":_+"小时"}const m=Math.floor(r/86400),o=Math.floor(r%86400/3600);return o?m+"天"+o+"小时":m+"天"}function fu(i){if(i==null)return null;const r=Number(i);return Number.isFinite(r)?r:null}function ng(i){const r=Date.now()/1e3,m=fu(i.started_at),o=fu(i.finished_at),_=fu(i.created_at);return m!==null&&o!==null&&o>=m?[zc(o-m),"总耗时:开始→结束(末次认领的执行时长)"]:m!==null&&i.status==="running"?["进行中 "+zc(r-m),"总耗时:进行中,已用时长从开始算起,随列表刷新更新"]:_!==null&&o!==null&&o>=_?[zc(o-_),"总耗时:创建→完成(含排队等待;无开始时间时的兜底口径)"]:_!==null&&(i.status==="queued"||i.status==="running")?[(i.status==="queued"?"排队中 ":"进行中 ")+zc(r-_),"总耗时:从创建算起的已用时长(无开始时间时的兜底口径)"]:["—","总耗时:无可用时间戳"]}function ug(i){const r=fu(i.total_tokens);if(r!==null)return[r.toLocaleString()+" token","token:服务端列表 total_tokens"];const m=fu(i.actual_tokens),o=fu(i.estimated_tokens);return m!==null||o!==null?[((m||0)+(o||0)).toLocaleString()+" token","token:actual + estimated 分项加总"]:["token —","token:本行未带 token 字段;单任务真数在任务详情的成本里可查,本行不逐个调成本接口、不编造"]}function ig({onNew:i}){const r=Mt();return s.jsxs("div",{children:[s.jsxs("div",{className:"search-box",children:[s.jsxs("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round","aria-hidden":"true",children:[s.jsx("circle",{cx:"11",cy:"11",r:"7"}),s.jsx("path",{d:"M21 21l-4.3-4.3"})]}),s.jsx("input",{type:"text",placeholder:"搜索","aria-label":"搜索任务",value:r.searchText,onChange:m=>r.setSearchText(m.target.value)})]}),s.jsx("div",{className:"bar",children:s.jsxs("select",{"aria-label":"项目",value:r.projectId,onChange:m=>r.selectProject(m.target.value),children:[r.projects.length===0?s.jsx("option",{value:"",children:"(先加载项目)"}):null,r.projects.map(m=>s.jsxs("option",{value:m.id,children:[m.name," (",Me(m.id),")"]},m.id))]})}),s.jsxs("div",{className:"list-section-head",children:[s.jsx("span",{children:"主要聊天"}),s.jsx("button",{type:"button","aria-label":"派发新任务",title:"派发新任务",onClick:i,children:"+"})]}),s.jsxs("div",{className:"bar",children:[s.jsxs("select",{"aria-label":"状态筛选",value:r.statusFilter,onChange:m=>r.setStatusFilter(m.target.value),children:[s.jsx("option",{value:"",children:"状态:全部"}),["queued","running","completed","failed","interrupted","merged","merge-failed"].map(m=>s.jsx("option",{value:m,children:m},m))]}),s.jsxs("select",{"aria-label":"执行器筛选",value:r.executorFilter,onChange:m=>r.setExecutorFilter(m.target.value),children:[s.jsx("option",{value:"",children:"执行器:全部"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"docker",children:"docker"}),s.jsx("option",{value:"cloud",children:"cloud"})]})]}),s.jsxs("div",{className:"bar",children:[s.jsx("button",{onClick:r.refreshTasks,children:"刷新"}),s.jsx("span",{className:"muted",children:r.taskCountText})]}),r.taskError?s.jsx("div",{className:"err",children:r.taskError}):r.projectId?r.filteredTasks.length===0?s.jsx("div",{className:"muted",children:r.tasks.length?"没有符合筛选条件的任务":"该项目暂无任务"}):s.jsx("ul",{className:"issue-list",children:r.filteredTasks.slice().reverse().map(m=>{var G;const[o,_]=ng(m),[C,N]=ug(m),x=ag(m);return s.jsxs("li",{className:"issue-item"+(((G=r.currentTask)==null?void 0:G.id)===m.id?" selected":""),onClick:()=>r.showDetail(m.id),children:[s.jsx("span",{className:"issue-state st-"+m.status,"aria-hidden":"true"}),s.jsx("span",{className:"issue-first",title:"任务首字:"+x,"aria-hidden":"true",children:x}),s.jsxs("span",{style:{flex:1,minWidth:0},children:[s.jsxs("div",{className:"issue-title",children:[m.plan?"[计划] ":"",m.forked_from?"[分支] ":"",m.coordinator_parts?"[协调] ":"",m.parent_task_id?"[协调子任务] ":"",String(m.prompt||Me(m.id)).slice(0,60)]}),s.jsxs("div",{className:"issue-meta",children:[Me(m.id)," · ",s.jsx("span",{className:"st-"+m.status,children:m.status})," · ",m.executor||"",m.updated_at?" · "+new Date(m.updated_at*1e3).toLocaleString():""," · ",s.jsxs("span",{title:_,children:["耗时 ",o]})," · ",s.jsx("span",{title:N,children:C})]})]})]},m.id)})}):s.jsx("div",{className:"muted",children:"先选项目"})]})}function cg(i){const r=v.useRef(null),[m,o]=v.useState(!0),_=v.useRef(!0),C=()=>{const N=r.current;if(!N)return;const x=N.scrollHeight-N.scrollTop-N.clientHeight<80;_.current=x,o(x)};return v.useEffect(()=>{_.current&&r.current&&(r.current.scrollTop=r.current.scrollHeight)},[i]),{ref:r,following:m,onScroll:C}}function sg({msg:i}){if(i.role==="status")return s.jsx("div",{className:"chat-status",children:i.text});const r=i.label||(i.role==="user"?"用户":i.role==="assistant"?"助手":"工具");return s.jsxs("div",{className:"gh-comment "+i.role,children:[s.jsx("div",{className:"gh-comment-header",children:s.jsx("span",{className:"gh-comment-author",children:r})}),s.jsx("div",{className:"gh-comment-body",children:i.text})]})}function kh({messages:i,empty:r}){const{ref:m,following:o,onScroll:_}=cg(i.length);return s.jsxs("div",{className:"chat-list",ref:m,onScroll:_,children:[i.length===0?s.jsx("div",{className:"muted",children:r||"(暂无消息)"}):i.map(C=>s.jsx(sg,{msg:C},C.id)),!o&&i.length>0?s.jsx("button",{className:"chat-follow",onClick:()=>{m.current&&(m.current.scrollTop=m.current.scrollHeight)},children:"回到最新 ↓"}):null]})}function fg({onSend:i,disabled:r,placeholder:m}){const[o,_]=v.useState(""),C=()=>{const N=o.trim();!N||r||(i(N),_(""))};return s.jsxs("div",{className:"gh-comment-box",children:[s.jsx("textarea",{"aria-label":"会话输入",rows:3,placeholder:m||"消息",value:o,disabled:r,onChange:N=>_(N.target.value),onKeyDown:N=>{N.key==="Enter"&&!N.shiftKey&&(N.preventDefault(),C())}}),s.jsx("div",{className:"gh-comment-footer",children:s.jsx("button",{type:"button",className:"primary","aria-label":"发送",disabled:r||!o.trim(),onClick:C,children:"发送"})})]})}function Xh(i,r){const m=i.id||"trace-"+r;if(i.kind==="message")return{id:m,role:"assistant",text:(i.phase?"["+i.phase+"] ":"")+(i.text||""),label:"助手"};if(i.kind==="exec"||i.kind==="file"||i.kind==="tool"||i.kind==="call"){const o=i.kind==="exec"?"命令":i.kind==="file"?"文件":i.kind==="tool"?"工具":"调用";return{id:m,role:"tool",text:or(i),label:o}}return i.kind==="plan"?{id:m,role:"status",text:i.text||""}:i.kind==="reasoning"?{id:m,role:"status",text:"思考:"+(i.summary||"")}:i.kind==="agent-start"?{id:m,role:"status",text:"子代理开始:"+(i.name||"")+(i.prompt?"("+i.prompt+")":"")}:i.kind==="agent-done"?{id:m,role:"status",text:"子代理结束:"+(i.name||"")+" "+(i.status||"")}:{id:m,role:"status",text:or(i)}}function rg(){const i=Mt(),r=v.useMemo(()=>{const m=i.currentTask,o=m&&m.prompt?[{id:"task-prompt",role:"user",text:m.prompt}]:[],C=(i.traceKind?i.traceEntries.filter(x=>x.kind===i.traceKind):i.traceEntries).map((x,G)=>Xh(x,G)),N=i.traceDone?[{id:"trace-done",role:"status",text:"链路已结束("+i.traceDone+")"}]:[];return[...o,...C,...N]},[i.currentTask,i.traceEntries,i.traceKind,i.traceDone]);return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"muted",children:"实时链路"}),s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"链路类型",value:i.traceKind,onChange:m=>i.setTraceKind(m.target.value),children:[s.jsx("option",{value:"",children:"链路类型:全部"}),["exec","file","call","tool","message","reasoning","plan","agent-start","agent-done"].map(m=>s.jsx("option",{value:m,children:m==="exec"?"命令":m==="file"?"文件":m==="call"?"调用":m==="tool"?"工具":m==="message"?"消息":m==="reasoning"?"思考":m==="plan"?"计划":"子代理"},m))]}),s.jsx("button",{onClick:i.downloadTrace,children:"下载完整链路"}),s.jsx("span",{className:"muted",children:i.traceMsg})]}),i.traceNote?s.jsx("div",{children:s.jsx("span",{className:"err",children:i.traceNote})}):null,s.jsx("div",{className:"chat-column",children:s.jsx(kh,{messages:r,empty:"(暂无链路条目)"})}),s.jsx("div",{className:"muted",children:"对话时间线:首条是本任务 prompt(用户);助手回复来自 message 条目,命令/文件/工具/调用是工具评论框,计划/思考/子代理开始结束是时间线上的状态文字。流式进行中时新条目实时追加;你在底部时自动跟随,往上翻时暂停跟随,点“回到最新”恢复。"})]})}function og(){const i=Mt(),r=i.currentTask,m=v.useMemo(()=>{if(!r)return[];if(i.chatHistory)return i.chatHistory.messages.map(b=>({id:b.id,role:b.role,text:b.text,label:b.label}));const G=r.prompt?[{id:"task-prompt",role:"user",text:r.prompt}]:[],U=i.traceEntries.filter(b=>b.kind==="message").map((b,B)=>Xh(b,B)),Q=i.followups.map((b,B)=>({id:"followup-"+B,role:"user",text:String(b.body||""),label:"后续消息"}));return[...G,...U,...Q]},[r,i.chatHistory,i.traceEntries,i.followups]);if(!r)return s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示继续会话"});const o=su.includes(r.status),_=["queued","running"].includes(r.status),C=o||_,N=o?"终态任务:发送走继续接口(同一会话再跑一轮)":_?"运行中/排队中:发送走后续消息直接发送(跑完当前轮后优先执行)":"merged/merge-failed 任务不可继续,也不可发后续消息",x=i.chatHistory?i.chatHistory.legacy_continue_count??null:null;return s.jsxs("div",{className:"chat-column",children:[x!==null&&x>0?s.jsxs("div",{className:"muted",children:["此前有 ",x," 条继续消息发生在持久化之前,未入库,上面历史不完整;部署后新发的继续消息会正常显示。"]}):null,i.chatHistory&&i.chatHistory.trace_note?s.jsx("div",{className:"muted",children:i.chatHistory.trace_note}):null,s.jsx(kh,{messages:m,empty:"(暂无会话消息)"}),s.jsx(fg,{disabled:!C,placeholder:"消息",onSend:G=>void i.sendChatMessage(G)}),s.jsxs("div",{className:"muted",children:[N,"。",i.chatMsg]})]})}function dg(){return Mt().currentTask?s.jsxs("div",{className:"conversation",children:[s.jsx(rg,{}),s.jsx("div",{className:"conv-divider"}),s.jsx(og,{})]}):s.jsx("div",{className:"conversation",children:s.jsx("div",{className:"muted",children:"在任务列表里点一条任务,对话和详情就切到该任务;也可以在上面派发一个新任务。"})})}function mg(){const i=Mt(),r=i.currentTask,[m,o]=v.useState("");if(!r)return null;const _=su.includes(r.status),C=["failed","interrupted","merge-failed"].includes(r.status);return s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("button",{disabled:!C,title:C?"":"仅 failed/interrupted/merge-failed 可重试",onClick:()=>i.doAction("retry"),children:"重试"}),s.jsx("button",{className:"danger",disabled:_,title:_?"终态任务不可取消":"",onClick:()=>i.doAction("cancel"),children:"取消"}),s.jsx("button",{disabled:r.status!=="completed",title:r.status!=="completed"?"仅 completed 可合并":"",onClick:()=>i.doAction("merge"),children:"合并(completed → merged)"}),s.jsx("button",{disabled:r.status!=="merged",title:r.status!=="merged"?"仅 merged 可提 PR":"",onClick:()=>i.doAction("pr"),children:"提 PR(须 merged)"}),_?s.jsx("button",{onClick:()=>i.setForkVisible(!0),children:"分支"}):null,s.jsx("button",{onClick:i.taskCost,children:"查成本"}),s.jsxs("span",{className:"muted",children:[i.actionMsg," ",i.actionReasons]})]}),i.forkVisible?s.jsxs("div",{children:[s.jsx("input",{type:"text",placeholder:"分支首轮消息(必填,带历史的新会话)",style:{width:"100%",boxSizing:"border-box",margin:"6px 0"},value:m,onChange:N=>o(N.target.value)}),s.jsxs(Dt,{children:[s.jsx("button",{className:"seal",onClick:async()=>{await i.forkTask(m),o("")},children:"创建分支任务"}),s.jsx("span",{className:"muted",children:i.forkMsg})]})]}):null]})}function hg(){const i=Mt(),[r,m]=v.useState("uncommittedChanges"),[o,_]=v.useState(""),[C,N]=v.useState(""),[x,G]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("h3",{children:"评审队列"}),s.jsxs("select",{"aria-label":"评审目标",value:r,onChange:U=>m(U.target.value),children:[s.jsx("option",{value:"uncommittedChanges",children:"未提交改动(工作区)"}),s.jsx("option",{value:"baseBranch",children:"与分支的差异"}),s.jsx("option",{value:"commit",children:"指定提交"}),s.jsx("option",{value:"custom",children:"自定义评审指令"})]}),s.jsx("input",{className:"stacked",placeholder:"与分支的差异用:分支名(如 main)",style:{width:"100%"},value:o,onChange:U=>_(U.target.value)}),s.jsx("input",{className:"stacked",placeholder:"指定提交用:提交 sha",style:{width:"100%"},value:C,onChange:U=>N(U.target.value)}),s.jsx("textarea",{placeholder:"自定义评审指令用:评审指令正文",value:x,onChange:U=>G(U.target.value)}),s.jsxs(Dt,{children:[s.jsx("button",{className:"primary",onClick:()=>void i.postReview({target_type:r,branch:o.trim()||void 0,sha:C.trim()||void 0,instructions:x.trim()||void 0}),children:"登记评审需求"}),s.jsx("button",{onClick:i.refreshReviews,children:"刷新队列"}),s.jsx("span",{className:"muted",children:i.reviewMsg})]}),s.jsx("div",{className:"muted",children:"本基线只登记评审需求(requested),不自动跑评审;评审是否执行、结果如何,以评审队列里的记录为准。"}),i.reviewError?s.jsx("div",{className:"muted",children:i.reviewError}):i.reviews.length===0?s.jsx("div",{className:"muted",children:"点任务行查看详情后,点“刷新队列”查看评审记录"}):s.jsx(ru,{children:i.reviews.map(U=>{let Q=U.target_type||"";return U.branch&&(Q+=":"+U.branch),U.sha&&(Q+=":"+String(U.sha).slice(0,12)),U.instructions&&(Q+=":"+String(U.instructions).slice(0,80)),s.jsxs("li",{children:[s.jsxs("span",{className:"row-main",children:[s.jsx("b",{children:"评审"})," ",Me(U.id)," | ",Q," | ",s.jsx("span",{className:"st-"+(U.status||""),children:U.status}),U.created_at?" | "+Xa(U.created_at):"",s.jsx("br",{}),U.findings?String(U.findings).slice(0,1e3):s.jsx("span",{className:"muted",children:"(暂无 findings:评审尚未执行或尚未写回)"})]}),s.jsx("button",{onClick:()=>i.submitFindings(U.id),children:"写 findings"})]},U.id)})})]})}function vg(){const i=Mt();return i.currentTask?i.currentTask.coordinator_parts?i.coordChildren.length===0?s.jsx("div",{className:"muted",children:"(子任务尚未创建)"}):s.jsx(ru,{children:i.coordChildren.map(r=>s.jsx("li",{children:s.jsxs("span",{className:"row-main",children:["分工 ",s.jsx("b",{children:r.coordinator_part||""})," | 状态 ",s.jsx("span",{className:"st-"+r.status,children:r.status})," | ",Me(r.id)," | ",String(r.prompt||"").slice(0,60)]})},r.id))}):s.jsx("div",{className:"muted",children:"(非协调员任务)"}):s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示协调员的子任务"})}function yg(){const i=Mt();if(!i.currentTask)return s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示子代理链路"});if(i.agents.length===0)return s.jsxs("div",{className:"muted",children:["(暂无子代理)",i.agentsNote?s.jsx("span",{className:"err",children:i.agentsNote}):null]});const r={main:"主任务",delegate:"委派子任务",model:"模型子代理"},m={running:"进行中",completed:"已完成",failed:"失败",interrupted:"已中断",unknown:"未知"};return s.jsx(ru,{children:i.agents.map((o,_)=>s.jsx("li",{children:s.jsxs("span",{className:"row-main",children:[s.jsxs("b",{children:[r[o.kind||""]||o.kind||"",":"]}),o.name||""," ",s.jsx("span",{className:"st-"+(o.status||""),children:m[o.status||""]||o.status||"?"})," | 过程调用 "+(o.calls?o.calls.length:0)+" 条",o.updated_ts?" | 最近活动 "+Xa(o.updated_ts/1e3):"",o.prompt?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsxs("span",{className:"muted",children:["任务:",o.prompt]})]}):null,o.calls&&o.calls.length?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),o.calls.slice(-50).map((C,N)=>s.jsx("div",{children:or(C)},N))]}):s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsx("span",{className:"muted",children:"(暂无过程调用)"})]})]})},_))})}function gg(){const i=Mt();return s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.refreshApprovals,children:"刷新审批队列"}),s.jsx("span",{className:"muted",children:i.approvalMsg})]}),s.jsx("div",{className:"muted",children:"待审批项需人工点记录允许或记录拒绝;超时默认拒绝。当前版本只留回执,不拦截实时行为(实时请求的事前拦截待 host 接入后生效,在此之前实时行为不变)。"}),s.jsx(Dl,{empty:"(暂无审批项)",items:i.approvals.map(r=>s.jsxs("span",{className:"row-main",children:["[",r.kind,"|",r.status,"] ",r.summary,["approved","denied","expired"].includes(r.status||"")?"|回执:"+(r.decision||r.status)+" by "+String(r.decided_by||"").slice(0,8)+" "+Xa(r.decided_at):"",r.status==="pending"?s.jsxs(s.Fragment,{children:[" ",s.jsx("button",{onClick:()=>i.decideApproval(r.id,"approved"),children:"记录允许"})," ",s.jsx("button",{onClick:()=>i.decideApproval(r.id,"denied"),children:"记录拒绝"})]}):null]},r.id))})]})}function pg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("input",{placeholder:"目标任务 id(与本任务同项目;对方运行中排队执行、已终态则续跑复活,绝不打断当前轮)",style:{width:"100%"},value:r,onChange:C=>m(C.target.value)}),s.jsx("textarea",{placeholder:"消息正文(以本任务名义发出;对方 agent 会看到发送方任务 id,可照此回消息)",value:o,onChange:C=>_(C.target.value)}),s.jsxs(Dt,{children:[s.jsx("button",{onClick:async()=>{await i.postPeer("queued",r,o),_("")},children:"排队发给对方"}),s.jsx("button",{className:"primary",onClick:async()=>{await i.postPeer("direct",r,o),_("")},children:"直接发送"}),s.jsx("span",{className:"muted",children:i.peerMsg})]}),s.jsx(Dl,{empty:"(本任务尚未发出任务间消息)",items:i.peerMessages.map((C,N)=>s.jsxs("span",{className:"row-main",children:["[发给 ",String(C.task_id).slice(0,8),"|",C.mode,"|",C.status,"] ",String(C.body||"").slice(0,120)]},N))})]})}function Sg(){const i=Mt(),[r,m]=v.useState(""),o=i.currentTask?["completed","failed","interrupted"].includes(i.currentTask.status):!1;return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"muted",children:i.threadText||"点任务行查看详情后,这里显示线程元数据"}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"新线程名",value:r,onChange:_=>m(_.target.value)}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("rename",r),children:"重命名"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("archive",""),children:"归档"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("unarchive",""),children:"取消归档"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("compact",""),children:"压缩"}),s.jsx("span",{className:"muted",children:i.threadGateNote}),s.jsx("span",{className:"muted",children:i.threadMsg})]}),s.jsx(Dl,{empty:"暂无其他线程",items:i.threadList.map((_,C)=>s.jsxs("span",{className:"row-main",children:[_.name||_.thread_name||_.id||""," [",_.id||"","]",_.archived?" [已归档]":"",_.cwd?" "+_.cwd:""]},C))}),s.jsx("div",{className:"muted",children:"限制:Docker/异机任务线程操作一律 409;merged/merge-failed 不可改;turn/steer 与 review/start 不在本批。"})]})}function bg(){const i=Mt(),r=i.currentTask;return r?s.jsxs(Ve,{id:"nav-detail",title:"任务详情",children:[s.jsxs("div",{children:["状态 ",s.jsx("b",{className:"st-"+r.status,children:r.status}),"(",Qy[r.status]||"未知状态",")",s.jsx("br",{}),"任务 ",r.id," | turn ",Me(r.turn_id)," | root turn ",Me(r.root_turn_id),s.jsx("br",{}),"executor ",r.executor||""," | 主机 ",r.worktree_host||"",s.jsx("br",{}),"模型 ",r.model||"默认"," | 强度 ",r.effort||"默认",r.child_model||r.child_effort?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"子任务默认 ",(r.child_model||"跟随本任务")+" / "+(r.child_effort||"跟随本任务")]}):null,s.jsx("br",{}),"权限 ",r.approval||"默认"," | 项目 ",Me(r.project_id),s.jsx("br",{}),"更新 ",Xa(r.updated_at),r.plan?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"计划模式(只读)"]}):null,r.forked_from?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"分支自 ",Me(r.forked_from)]}):null,r.goal_mode?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),r.no_time_limit?"goal 模式无敌版(不限时)":"goal 模式(不限轮次,模型宣告完成)"]}):r.verify_command?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"goal 模式(旧语义,验收命令)"]}):null,r.coordinator_parts?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"协调员:",r.coordinator_parts.length," 个子任务(",r.coordinator_parts.map(m=>m.name).join("、"),")"]}):null,r.parent_task_id?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"协调子任务,父任务 ",Me(r.parent_task_id),r.coordinator_part?"("+r.coordinator_part+")":""]}):null,r.attachments&&r.attachments.length?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"附件:",r.attachments.join("、")]}):null,r.pr_url?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsxs("a",{href:r.pr_url,target:"_blank",rel:"noopener noreferrer",children:["PR #",r.pr_number]})]}):null,s.jsx("br",{}),"prompt:",r.prompt||""]}),s.jsx(mg,{}),s.jsx("pre",{children:i.detailBody||"(暂无 result/error 输出)"}),i.costBox?s.jsx("pre",{children:i.costBox}):null,s.jsx("h3",{children:"协调子任务"}),s.jsx(vg,{}),s.jsx("h3",{children:"子代理链路"}),s.jsx(yg,{}),s.jsx("h3",{children:"评审队列"}),s.jsx(hg,{}),s.jsx("h3",{children:"运行时审批队列"}),s.jsx(gg,{}),s.jsx("h3",{children:"给其他任务发消息"}),s.jsx(pg,{}),s.jsx("h3",{children:"线程"}),s.jsx(Sg,{})]}):s.jsx(Ve,{id:"nav-detail",title:"任务详情",children:s.jsx("div",{className:"muted",children:"点任务行查看详情"})})}function jg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState([]),[x,G]=v.useState(null),[U,Q]=v.useState(!1),[b,B]=v.useState(""),[lt,at]=v.useState(""),I=v.useCallback(async()=>{if(!i.keySaved){N([]);return}try{const nt=await tt($.userKeys);N(nt.keys||[]),at("")}catch(nt){at(nt instanceof Error?nt.message:"加载 key 列表失败")}},[i.keySaved]);v.useEffect(()=>{I()},[I]);const V=async()=>{B(""),at(""),Q(!1);try{const nt=await tt($.userKeys,"POST",{label:o.trim()||"api-key"});G(nt),_(""),B("新 key 已生成,只显示一次:复制后请妥善保存。"),await I()}catch(nt){at(nt instanceof Error?nt.message:"生成 key 失败")}},dt=async()=>{if(x)try{await navigator.clipboard.writeText(x.api_key),Q(!0)}catch{at("复制失败:请手动选中上方 key 文本复制")}},Ot=()=>{x&&(i.saveKeyInput(x.api_key),G(null),B("已存为当前浏览器 key(原有 key 未被撤销,需要时可单独撤销)。"))},te=async nt=>{const Xt=(()=>{try{return _l().slice(-4)}catch{return""}})(),ee=nt.id==="legacy"?"(主 key:撤销后当前浏览器保存的 key 也可能随之失效,需重新登录拿新 key)":nt.hint&&nt.hint===Xt?"(这就是本浏览器当前在用的 key,撤销后本页会立刻未连接)":"";if(window.confirm(`撤销 key「${nt.label}」(后 4 位 ${nt.hint||"无"})吗?${ee}撤销不可恢复。`)){B(""),at("");try{await tt($.userKey(nt.id),"DELETE"),B(`已撤销 key「${nt.label}」。`),await I()}catch(ct){at(ct instanceof Error?ct.message:"撤销失败")}}};return s.jsxs(Ve,{id:"nav-key",title:"API Key",children:[s.jsxs(Dt,{children:[s.jsx("input",{type:"password",placeholder:"粘贴你的 X-API-Key(与调 API 用的同一个)",autoComplete:"off",value:r,onChange:nt=>m(nt.target.value)}),s.jsx("button",{className:"primary",onClick:()=>{i.saveKeyInput(r),m("")},children:"保存到本浏览器"}),s.jsx("button",{onClick:i.clearKeyInput,children:"清除"}),s.jsx("span",{className:"muted",children:i.keyState})]}),s.jsx("div",{children:s.jsx("span",{className:"muted",children:i.quotaText})}),!i.keySaved&&s.jsx("div",{children:s.jsx("span",{className:"muted",children:"先粘贴并保存已有 key,再生成或管理 key(生成接口本身也要用已有 key 鉴权)。"})}),i.keySaved&&s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("input",{placeholder:"新 key 备注(可选,默认 api-key,如 harness2-temp)",autoComplete:"off",value:o,onChange:nt=>_(nt.target.value)}),s.jsx("button",{className:"primary",onClick:()=>void V(),children:"生成新 key"}),s.jsx("button",{onClick:()=>void I(),children:"刷新列表"})]}),x&&s.jsxs("div",{children:[s.jsx("div",{children:s.jsxs("span",{className:"muted",children:["新 key(",x.label,",后 4 位 ",x.hint,"):只显示一次,关闭后无法再查看。"]})}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",readOnly:!0,value:x.api_key,onFocus:nt=>nt.target.select()}),s.jsx("button",{className:"primary",onClick:()=>void dt(),children:U?"已复制":"复制"}),s.jsx("button",{onClick:Ot,children:"存为当前浏览器 key"}),s.jsx("button",{onClick:()=>G(null),children:"关闭(不再显示)"})]})]}),b&&s.jsx("div",{children:s.jsx("span",{className:"muted",children:b})}),lt&&s.jsx("div",{children:s.jsx("span",{children:lt})}),s.jsxs("div",{children:[C.length===0&&s.jsx("span",{className:"muted",children:"暂无 key(或列表加载失败,见上方报错)。"}),C.map(nt=>s.jsxs("div",{children:[s.jsx("span",{children:nt.label})," ",s.jsxs("span",{className:"muted",children:["后 4 位 ",nt.hint||"无"," · 创建 ",Xa(nt.created_at)," · 最近使用 ",nt.last_used_at?Xa(nt.last_used_at):"未使用过"]})," ",nt.revoked_at?s.jsxs("span",{className:"muted",children:["已撤销(",Xa(nt.revoked_at),")"]}):s.jsx("button",{onClick:()=>void te(nt),children:"撤销"})]},nt.id))]})]})]})}function xg(){const i=Mt();return s.jsxs(Ve,{id:"adminCard",title:s.jsxs(s.Fragment,{children:["管理区 ",s.jsx("span",{className:"muted",children:"(仅全局管理员)"})]}),children:[s.jsx("div",{className:"muted",children:i.adminGate}),i.adminBody?s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"要查配额的用户 id",value:i.adminUserId,onChange:r=>i.setAdminUserId(r.target.value)}),s.jsx("button",{onClick:i.adminQuota,children:"查该用户配额"})]}),s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.adminSweep,children:"手动触发 sweep(清理陈旧 running 任务)"}),s.jsx("button",{onClick:i.adminBackup,children:"手动触发备份"})]}),s.jsx("div",{className:"muted",children:i.adminResult})]}):null]})}function Tg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState("");return s.jsxs(Ve,{id:"nav-projects",title:"项目",children:[s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"项目",value:i.projectId,onChange:x=>i.selectProject(x.target.value),children:[i.projects.length===0?s.jsx("option",{value:"",children:"(先加载项目)"}):null,i.projects.map(x=>s.jsxs("option",{value:x.id,children:[x.name," (",Me(x.id),")"]},x.id))]}),s.jsx("button",{onClick:i.refreshProjects,children:"刷新"})]}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"新项目名",value:r,onChange:x=>m(x.target.value)}),s.jsxs("select",{"aria-label":"从 GitHub 仓库选",value:o,onChange:x=>{_(x.target.value),x.target.value&&N(x.target.value)},children:[s.jsx("option",{value:"",children:"(从 GitHub App 安装仓库里选,或手动输入)"}),i.githubRepos.map(x=>s.jsx("option",{value:x.clone_url,children:x.repo_full_name},x.clone_url))]}),s.jsx("input",{type:"text",placeholder:"repo_url(可选)",value:C,onChange:x=>N(x.target.value)}),s.jsx("button",{onClick:async()=>{await i.createProject(r,C),m(""),N(""),_("")},children:"新建项目"})]}),s.jsx("span",{className:"muted",children:i.projectMsg})]})}function _g(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState("contributor"),C=i.projects.find(N=>N.id===i.projectId);return s.jsxs(Ve,{title:"项目成员",children:[C?s.jsxs("div",{className:"muted",children:[C.name," | ",C.id," | 仓库 ",C.repo_url||"未绑定"," | 我的角色 ",C.my_role||"未知"]}):s.jsx("div",{className:"muted",children:"先选项目"}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"成员 user_id 或用户名",value:r,onChange:N=>m(N.target.value)}),s.jsxs("select",{"aria-label":"邀请角色",value:o,onChange:N=>_(N.target.value),children:[s.jsx("option",{value:"viewer",children:"viewer(只读)"}),s.jsx("option",{value:"contributor",children:"contributor(可建任务)"}),s.jsx("option",{value:"maintainer",children:"maintainer(可批合并)"}),s.jsx("option",{value:"owner",children:"owner(可管项目)"})]}),s.jsx("button",{onClick:async()=>{await i.inviteMember(r,o),m("")},children:"邀请成员"}),s.jsx("button",{onClick:i.refreshMembers,children:"刷新成员"})]}),i.memberError?s.jsx("div",{className:"muted",children:i.memberError}):i.members.length===0?s.jsx("div",{className:"muted",children:"先选项目"}):s.jsx(ru,{children:i.members.map(N=>{const x=(N.username||"")+(N.username?"("+String(N.user_id).slice(0,8)+")":String(N.user_id).slice(0,8));return s.jsxs("li",{children:[s.jsx("span",{className:"row-main",children:x}),s.jsx("select",{"aria-label":"成员角色",value:N.role||"viewer",onChange:G=>void i.changeMemberRole(N.user_id,G.target.value),children:ky.map(G=>s.jsx("option",{value:G,children:G},G))})]},N.user_id)})}),s.jsx("span",{className:"muted",children:i.memberMsg})]})}function Eg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState("");return s.jsxs(Ve,{id:"nav-env",title:s.jsxs(s.Fragment,{children:["环境 ",s.jsx("span",{className:"muted",children:"(选、建、管:当前项目的基准检出)"})]}),children:[s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.refreshEnvs,children:"刷新"}),s.jsx("span",{className:"muted",children:i.envCount})]}),i.envs.length===0?s.jsx("div",{className:"muted",children:"先选项目"}):s.jsx(ru,{children:i.envs.map(x=>s.jsxs("li",{children:[s.jsxs("span",{className:"row-main",children:[x.name,"(",Me(x.id),") / 分支 ",x.branch||"默认分支"," / 执行器 ",x.executor||"不限"," / 状态 ",x.status,x.status==="failed"&&x.error_text?" / 失败原因:"+x.error_text:""]}),x.status==="archived"?null:s.jsx("button",{onClick:()=>void i.archiveEnv(x.id),children:"归档"})]},x.id))}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"新环境名",value:r,onChange:x=>m(x.target.value)}),s.jsx("input",{type:"text",placeholder:"分支(可选,空=默认分支)",value:o,onChange:x=>_(x.target.value)}),s.jsxs("select",{"aria-label":"新环境执行器",value:C,onChange:x=>N(x.target.value),children:[s.jsx("option",{value:"",children:"执行器:不限"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"docker",children:"docker"})]}),s.jsx("button",{onClick:async()=>{await i.createEnv(r,o,C),m(""),_("")},children:"新建环境"})]}),s.jsx("span",{className:"muted",children:i.envMsg})]})}function Ng(){const i=Mt(),[r,m]=v.useState("");return s.jsxs(Ve,{title:"仓库与环境上下文",children:[s.jsx("div",{className:"muted",children:i.envRepoLine||"先选项目"}),s.jsx("div",{className:"muted",children:i.envCount}),i.envRepoBar?s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"补仓库",value:r,onChange:o=>m(o.target.value),children:[s.jsx("option",{value:"",children:"(从 GitHub App 安装仓库里选)"}),i.githubRepos.map(o=>s.jsx("option",{value:o.clone_url,children:o.repo_full_name},o.clone_url))]}),s.jsx("button",{onClick:()=>void i.saveEnvRepo(r),children:"保存仓库"})]}):null,s.jsx("span",{className:"muted",children:i.envRepoMsg})]})}function Cg(){const i=Mt();return s.jsxs(Ve,{id:"nav-workers",title:"Workers",children:[s.jsx(Dt,{children:s.jsx("button",{onClick:i.refreshWorkers,children:"刷新"})}),i.workersError?s.jsx("div",{className:"muted",children:i.workersError}):i.workers===null?s.jsx("div",{className:"muted",children:i.workersSummary||"未加载"}):i.workers.length===0?s.jsx("div",{className:"muted",children:"无 worker 注册"}):s.jsx(ru,{children:i.workers.map((r,m)=>{const o=r.running===void 0||r.running===null?"?":r.running,_=r.capacity===void 0||r.capacity===null?"?":r.capacity,C=Qh(r),N=r.alive!==void 0&&r.alive!==null?!!r.alive:C.age!==null&&C.age<=120,x=N?" / 在线":" / 离线(占用为上次上报值)";return s.jsx("li",{className:N?"is-online":"is-offline",children:s.jsxs("span",{className:"row-main",children:[r.worker_id||r.id||"?"," / ",r.executor||""," / 占用 ",o,"/",_,x," / 最后心跳 ",C.text]})},m)})})]})}function Ag(){const i=Mt();return s.jsxs(Ve,{title:"健康与配额",children:[s.jsxs(Dt,{children:[s.jsx("span",{className:"muted",children:i.healthText}),s.jsx("button",{onClick:i.refreshHealth,children:"刷新"})]}),s.jsx("div",{children:s.jsx("span",{className:"muted",children:i.quotaText})}),s.jsx("div",{className:"muted",children:i.workersSummary})]})}function Mg(){const i=Mt();return s.jsxs(Ve,{id:"nav-skills",title:"技能与 MCP",children:[s.jsx("div",{className:"muted",children:"反映宿主租户 home,容器内 home 可能不同;重载只在 schema 枚举里,当前 pin 的二进制拒绝时原样 502;OAuth 只发起登录,不代表登录完成。"}),s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.refreshSkills,children:"刷新"}),s.jsx("span",{className:"muted",children:i.skillMsg})]}),s.jsx("h3",{children:"技能"}),i.skillError?s.jsx("div",{className:"muted",children:i.skillError}):s.jsx(Dl,{empty:"暂无技能",items:i.skills.map((r,m)=>s.jsxs("span",{className:"row-main",children:[r.name||r.id||"",r.description?" - "+r.description:"",r.detail?" - "+r.detail:""]},m))}),s.jsx("h3",{children:"应用"}),s.jsx(Dl,{empty:"暂无应用",items:i.apps.map((r,m)=>s.jsxs("span",{className:"row-main",children:[r.name||r.id||"",r.description?" - "+r.description:""]},m))}),s.jsx("h3",{children:"MCP 服务"}),s.jsx(Dl,{empty:"暂无 MCP 服务",items:i.mcpServers.map((r,m)=>{const o=r.detail||r.details||r.state||"";return s.jsxs("span",{className:"row-main",children:[r.name||r.id||""," | 状态 ",r.status||"",o?" | "+o:""]},m)})})]})}function Og(){const i=Mt(),[r,m]=v.useState("");return s.jsxs(Ve,{title:"MCP 操作",children:[s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.reloadMcp,children:"重载配置"}),s.jsx("span",{className:"muted",children:i.mcpMsg})]}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"MCP 服务名",value:r,onChange:o=>m(o.target.value)}),s.jsx("button",{onClick:()=>void i.mcpOauth(r),children:"发起 OAuth 登录"}),s.jsx("span",{className:"muted",children:i.mcpOauthMsg})]}),i.mcpOauthBox?s.jsx("pre",{children:i.mcpOauthBox}):null]})}function zg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState(""),[x,G]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("input",{placeholder:"自动化名称(同项目内启用中的名称唯一)",style:{width:"100%"},value:r,onChange:U=>m(U.target.value)}),s.jsx("textarea",{placeholder:"定时任务内容(创建只登记定义与到期状态;执行由后续执行器经 claim 抢单后建任务,不另起调度器)",value:o,onChange:U=>_(U.target.value)}),s.jsxs(Dt,{children:[s.jsx("input",{placeholder:"间隔秒数(默认 86400,最小 60)",style:{width:"40%"},value:C,onChange:U=>N(U.target.value)}),s.jsx("input",{placeholder:"仓库(可选)",style:{width:"40%"},value:x,onChange:U=>G(U.target.value)}),s.jsx("button",{className:"primary",onClick:async()=>{await i.createAutomation(r,o,C,x),m(""),_(""),N(""),G("")},children:"创建自动化"}),s.jsx("button",{onClick:i.refreshAutomations,children:"刷新自动化"}),s.jsx("span",{className:"muted",children:i.autoMsg})]}),s.jsx(Dl,{empty:"(暂无自动化)",items:i.automations.map(U=>s.jsxs("span",{className:"row-main",children:["[",U.status,U.due?"|到期":"","] ",U.name,"|每 ",U.interval_seconds," 秒|下次 ",Xa(U.next_run_at),U.status==="active"?s.jsxs(s.Fragment,{children:[" ",s.jsx("button",{onClick:()=>i.cancelAutomation(U.id),children:"取消"})]}):null]},U.id))})]})}function Rg(){var m,o,_,C;const i=Mt(),r=i.triage;return i.triageError?s.jsx("div",{className:"muted",children:i.triageError}):r?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["到期自动化(",((m=r.counts)==null?void 0:m.automations_due)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.automations_due||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[N.name,"|每 ",N.interval_seconds," 秒"]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["失败/中断任务(",((o=r.counts)==null?void 0:o.failed_tasks)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.failed_tasks||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[Me(N.id),"|",N.status,"|",String(N.prompt||"").slice(0,80)]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["待处理后续消息(",((_=r.counts)==null?void 0:_.pending_followups)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.pending_followups||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:["任务 ",Me(N.task_id),"|",String(N.body||"").slice(0,80)]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["最近自动化产出(",((C=r.counts)==null?void 0:C.recent_runs)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.recent_runs||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[Me(N.automation_id),"|",N.status,N.task_id?"|任务 "+Me(N.task_id):"",N.task_status?"|"+N.task_status:""]},x))})]})]}):s.jsx("div",{className:"muted",children:"(先选项目)"})}function Dg(){return s.jsx(Ve,{id:"nav-automations",title:"自动化",children:s.jsx(zg,{})})}function Ug(){const i=Mt();return s.jsxs(Ve,{id:"nav-triage",title:"分诊收件箱",children:[s.jsx(Dt,{children:s.jsx("button",{onClick:i.refreshTriage,children:"刷新分诊"})}),s.jsx(Rg,{})]})}const Hg=[["#sec-dispatch","派发"],["#sec-tasks","任务"],["#sec-conv","对话"],["#sec-projects","项目"],["#sec-env","环境"],["#sec-workers","Workers"],["#sec-skills","技能"],["#sec-automations","自动化"],["#sec-triage","分诊"],["#sec-admin","管理区"],["#sec-key","API Key"]];function Bg(){return s.jsxs("header",{className:"dash-topbar",children:[s.jsxs("div",{className:"dash-topbar-row",children:[s.jsx("span",{className:"dash-brand",children:"Codex 命令台"}),s.jsx(qg,{}),s.jsx("span",{className:"muted dash-hide-sm",children:s.jsx(Yg,{})}),s.jsx("span",{className:"muted dash-hide-sm",children:s.jsx(wg,{})}),s.jsx("span",{className:"muted dash-stamp",children:s.jsx(Gg,{})})]}),s.jsx("nav",{className:"dash-nav","aria-label":"页面导航",children:Hg.map(([i,r])=>s.jsx("a",{href:i,children:r},i))})]})}function qg(){const i=Mt();return s.jsx("span",{className:i.keySaved?"dash-status ok":"dash-status off",children:i.keySaved?"● 已连接":"○ 未连接"})}function Yg(){return s.jsx(s.Fragment,{children:Mt().healthText})}function wg(){return s.jsx(s.Fragment,{children:Mt().quotaText})}function Gg(){return s.jsxs(s.Fragment,{children:["自动刷新 · 每 10 秒 · 已刷新 ",Mt().refreshStamp]})}function Qg(){const i=tg();$y(m=>i.refreshAll(m),1e4),Iy(()=>i.refreshSlow(),6e4);const r=()=>{var m;(m=document.getElementById("sec-dispatch"))==null||m.scrollIntoView({behavior:"smooth"})};return s.jsxs(Gh.Provider,{value:i,children:[s.jsx(Bg,{}),s.jsxs("main",{className:"dash-page",children:[s.jsx(eg,{}),s.jsxs("div",{className:"dash-col dash-col-left",children:[s.jsxs("section",{id:"sec-tasks",className:"dash-section card",children:[s.jsx("h2",{children:"任务列表"}),s.jsx(ig,{onNew:r})]}),s.jsxs("section",{id:"sec-projects",className:"dash-section",children:[s.jsx(Tg,{}),s.jsx(_g,{})]})]}),s.jsxs("div",{className:"dash-col dash-col-mid",children:[s.jsx("section",{id:"sec-dispatch",className:"dash-section",children:s.jsx(lg,{})}),s.jsxs("section",{id:"sec-conv",className:"dash-section",children:[s.jsxs("div",{className:"card",children:[s.jsx("h2",{children:"对话"}),s.jsx(dg,{})]}),s.jsx(bg,{})]})]}),s.jsxs("div",{className:"dash-col dash-col-right",children:[s.jsxs("section",{id:"sec-env",className:"dash-section",children:[s.jsx(Eg,{}),s.jsx(Ng,{})]}),s.jsxs("section",{id:"sec-workers",className:"dash-section",children:[s.jsx(Cg,{}),s.jsx(Ag,{})]}),s.jsxs("section",{id:"sec-skills",className:"dash-section",children:[s.jsx(Mg,{}),s.jsx(Og,{})]}),s.jsx("section",{id:"sec-automations",className:"dash-section",children:s.jsx(Dg,{})}),s.jsx("section",{id:"sec-triage",className:"dash-section",children:s.jsx(Ug,{})}),s.jsx("section",{id:"sec-admin",className:"dash-section",children:s.jsx(xg,{})}),s.jsx("section",{id:"sec-key",className:"dash-section",children:s.jsx(jg,{})})]})]})]})}wy.createRoot(document.getElementById("root")).render(s.jsx(zy.StrictMode,{children:s.jsx(Qg,{})})); +`),C(L||"(暂无 result/error 输出)")}catch{}dl(H.id),Bl(H.id),Ye(H.id),Vt(H.id),Hl(H),ol(H.id),ll(H.id),ml(H.id),ql(H.id)}},[dl,Bl,Ye,Vt,Hl,ol,ll,ml,ql]),gn=v.useCallback(async H=>{const D=ne.current;if(!D)return;const L={cancel:"确定取消该任务吗?",merge:"确定把 completed 任务标为 merged 吗?",pr:"确定为该任务提 PR 吗?(会在仓库真实建 PR)"};if(!(L[H]&&!window.confirm(L[H])))try{const J=await tt($.taskAction(D.id,H),"POST",{});x(H+" 已提交:"+JSON.stringify(J).slice(0,300)),r(),await Wl(D.id)}catch(J){x(H+" 失败:"+J.message)}},[Wl,r]),Ke=v.useCallback(async()=>{const H=ne.current;if(H)try{const D=await tt($.taskCost(H.id));b(JSON.stringify(D,null,2).slice(0,4e3))}catch(D){b("查成本失败:"+D.message)}},[]),Za=v.useCallback(async H=>{const D=ne.current;if(D){if(!H.trim()){I("分支消息必填");return}if(!su.includes(D.status)){I("仅终态任务可分支");return}try{const L=await tt($.taskFork(D.id),"POST",{message:H.trim()});I("分支任务已建:"+L.id.slice(0,8)),r()}catch(L){I("分支失败:"+L.message)}}},[r]),va=v.useCallback(async H=>{const D=ne.current;if(D)try{await tt($.taskReviews(D.id),"POST",H),le("评审已登记(requested)"),await Ye(D.id)}catch(L){le("登记评审需求失败:"+L.message)}},[Ye]),ou=v.useCallback(H=>{const D=ne.current;if(!D)return;const L=window.prompt("输入该条评审的 findings(将写回记录并标为 completed):");L!==null&&tt($.taskReviewFindings(D.id,H),"POST",{findings:L}).then(()=>void Ye(D.id)).catch(J=>le("写 findings 失败:"+J.message))},[Ye]),du=v.useCallback((H,D)=>{const L=ne.current;if(!L)return;const J=D==="approved"?"approve":"deny";tt($.taskApprovalDecision(L.id,H,J),"POST",{}).then(()=>{K("已记录"+(D==="approved"?"允许":"拒绝")+"(当前版本只留回执,不拦截实时行为)"),Vt(L.id)}).catch(Ct=>K("决定失败:"+Ct.message))},[Vt]),$l=v.useCallback(async(H,D,L)=>{const J=ne.current;if(J){if(!D.trim()){k("目标任务 id 不能为空");return}if(!L.trim()){k("消息正文不能为空");return}try{const Ct=await tt($.taskMessagesTo(D.trim()),"POST",{from_task_id:J.id,body:L.trim(),mode:H});k("已发送("+Ct.delivery+")"),await ll(J.id)}catch(Ct){k("发送失败:"+Ct.message)}}},[ll]),Se=v.useCallback((H,D)=>{const L=ne.current;if(!L)return;if(!["completed","failed","interrupted"].includes(L.status)){Gt("仅 completed/failed/interrupted 任务可操作线程(merged/merge-failed 不可改,服务端同样 409)");return}const J={};if(H==="rename"){if(!D.trim()){Gt("新线程名不能为空");return}J.name=D.trim()}tt($.taskThreadAction(L.id,H),"POST",J).then(Ct=>{Gt(H+" 已提交:"+JSON.stringify(Ct).slice(0,300)),ml(L.id),ql(L.id)}).catch(Ct=>Gt(H+" 失败:"+Ct.message))},[ml,ql]),hl=v.useCallback(async H=>{const D=ne.current;if(!D)return;const L=H.trim();if(!L){ae("消息不能为空");return}try{su.includes(D.status)&&D.status!=="merged"?(await tt($.taskContinue(D.id),"POST",{message:L}),ae("已重新排队,同一会话继续"),r(),await Wl(D.id)):["queued","running"].includes(D.status)?(await tt($.taskFollowups(D.id),"POST",{body:L,mode:"direct"}),ae("已直接发送"),await dl(D.id),await Bl(D.id)):ae("merged/merge-failed 任务不可继续,也不可发后续消息")}catch(J){ae("发送失败:"+J.message)}},[Wl,r,dl,Bl]),be=v.useCallback(async()=>{const H=ne.current;if(!H){ie("先选一个任务");return}try{const D=await tt($.taskTrace(H.id)),L=new Blob([JSON.stringify({task_id:H.id,status:D.status,note:D.note||"",count:(D.entries||[]).length,entries:D.entries||[]},null,2)],{type:"application/json"}),J=document.createElement("a");J.href=URL.createObjectURL(L),J.download="trace-"+H.id.slice(0,8)+".json",document.body.appendChild(J),J.click(),J.remove(),setTimeout(()=>URL.revokeObjectURL(J.href),1e3),ie("已下载完整链路 "+(D.entries||[]).length+" 条")}catch(D){ie("下载失败:"+D.message)}},[]);return v.useEffect(()=>()=>qe(),[qe]),{currentTask:m,detailBody:_,actionMsg:N,actionReasons:G,costBox:Q,forkVisible:B,setForkVisible:lt,forkMsg:at,coordChildren:V,agents:Ot,agentsNote:nt,reviews:ee,reviewMsg:yt,reviewError:de,traceEntries:Ft,traceNote:tl,traceDone:Y,traceKind:et,setTraceKind:Tt,traceMsg:gt,followups:Oe,approvals:y,approvalMsg:F,peerMessages:pt,peerMsg:_t,threadText:ut,threadGateNote:Va,threadMsg:Le,threadList:zt,chatMsg:Fl,chatHistory:ha,showDetail:Wl,refreshDetailLists:yn,doAction:gn,taskCost:Ke,forkTask:Za,postReview:va,submitFindings:ou,decideApproval:du,postPeer:$l,threadAction:Se,sendChatMessage:hl,downloadTrace:be,refreshReviews:()=>void Ye(),refreshApprovals:()=>void Vt()}}function Py(i){const[r,m]=v.useState([]),[o,_]=v.useState(""),[C,N]=v.useState(null),[x,G]=v.useState(""),U=v.useCallback(async lt=>{const at=lt!==void 0?lt:i();if(!at){m([]);return}try{const I=await tt($.projectAutomations(at));m(I.automations||[])}catch(I){_("自动化加载失败:"+I.message)}},[i]),Q=v.useCallback(async(lt,at,I,V)=>{const dt=i();if(!dt){_("先选项目");return}if(!lt.trim()){_("自动化名称必填");return}if(!at.trim()){_("定时任务内容必填");return}const Ot={name:lt.trim(),prompt:at.trim()};I.trim()&&(Ot.interval_seconds=parseInt(I.trim(),10)),V.trim()&&(Ot.repo_url=V.trim());try{await tt($.projectAutomations(dt),"POST",Ot),_("自动化已创建(登记定义,到期后由执行器认领)"),await U(dt)}catch(te){_("创建失败:"+te.message)}},[i,U]),b=v.useCallback(lt=>{const at=i();at&&tt($.projectAutomationCancel(at,lt),"POST",{}).then(()=>{_("自动化已取消"),U(at)}).catch(I=>_("取消失败:"+I.message))},[i,U]),B=v.useCallback(async lt=>{const at=lt!==void 0?lt:i();if(!at){N(null);return}try{const I=await tt($.projectTriage(at));N(I),G("")}catch(I){G("分诊加载失败:"+I.message)}},[i]);return{automations:r,autoMsg:o,triage:C,triageError:x,refreshAutomations:U,createAutomation:Q,cancelAutomation:b,refreshTriage:B}}function tg(i,r){const m=v.useRef(i);m.current=i,v.useEffect(()=>{const o=setInterval(()=>{const _=document.activeElement;m.current(_?_.tagName==="SELECT":!1)},r);return()=>clearInterval(o)},[r])}function eg(i,r){const m=v.useRef(i);m.current=i,v.useEffect(()=>{const o=setInterval(()=>m.current(),r);return()=>clearInterval(o)},[r])}function lg(i){const r=m=>String(m).padStart(2,"0");return r(i.getHours())+":"+r(i.getMinutes())+":"+r(i.getSeconds())}function ag(){var I;const i=Wy(),r=$y(),m=v.useRef("");m.current=i.projectId;const o=v.useCallback(()=>m.current,[]),_=Py(o),C=v.useCallback(V=>{const dt=i.projects.find(Ot=>Ot.id===V);return dt&&dt.my_role||null},[i.projects]),N=v.useCallback(()=>{r.refreshTasks(void 0,m.current)},[r]),x=Iy(C,N),[G,U]=v.useState("--:--:--"),Q=v.useCallback(V=>{i.setProjectId(V),m.current=V,r.refreshTasks(V),i.refreshEnvs(V),i.refreshMembers(V),i.refreshSkills(V),_.refreshAutomations(V),_.refreshTriage(V)},[i,r,_]),b=(I=i.projects[0])==null?void 0:I.id;v.useEffect(()=>{!i.projectId&&b&&Q(b)},[i.projectId,b,Q]);const B=v.useCallback(V=>{i.saveKeyInput(V),V.trim()&&(i.refreshHealth(),i.refreshProjects(),i.refreshWorkers(),m.current&&(r.refreshTasks(m.current),i.refreshEnvs(m.current),i.refreshMembers(m.current)),i.loadRelayModels(),i.loadQuota(),i.loadGithubRepos(),i.probeAdmin())},[i,r]),lt=v.useCallback(V=>{if(U(lg(new Date)),!_l()){i.refreshHealth();return}r.refreshTasks(void 0,m.current),i.refreshHealth(),i.loadQuota(),i.refreshWorkers(),i.refreshMembers(),i.refreshSkills(),_.refreshAutomations(),_.refreshTriage(),x.refreshDetailLists(),V||(i.refreshProjects(),i.refreshEnvs())},[i,r,_,x]),at=v.useCallback(()=>{_l()&&(i.loadRelayModels(),i.loadGithubRepos())},[i]);return v.useEffect(()=>{i.refreshHealth(),i.refreshProjects(),i.refreshWorkers(),i.loadQuota(),i.loadGithubRepos(),_l()&&i.loadRelayModels(),i.probeAdmin()},[]),{keySaved:i.keySaved,keyState:i.keyState,saveKeyInput:B,clearKeyInput:i.clearKeyInput,quotaText:i.quotaText,healthText:i.healthText,refreshHealth:i.refreshHealth,adminGate:i.adminGate,adminBody:i.adminBody,adminResult:i.adminResult,adminUserId:i.adminUserId,setAdminUserId:i.setAdminUserId,adminQuota:i.adminQuota,adminSweep:i.adminSweep,adminBackup:i.adminBackup,projects:i.projects,projectId:i.projectId,projectMsg:i.projectMsg,selectProject:Q,refreshProjects:i.refreshProjects,createProject:i.createProject,githubRepos:i.githubRepos,workers:i.workers,workersSummary:i.workersSummary,workersError:i.workersError,refreshWorkers:i.refreshWorkers,members:i.members,memberMsg:i.memberMsg,memberError:i.memberError,refreshMembers:()=>void i.refreshMembers(),inviteMember:i.inviteMember,changeMemberRole:i.changeMemberRole,skills:i.skills,apps:i.apps,mcpServers:i.mcpServers,skillMsg:i.skillMsg,skillError:i.skillError,mcpMsg:i.mcpMsg,mcpOauthMsg:i.mcpOauthMsg,mcpOauthBox:i.mcpOauthBox,refreshSkills:()=>void i.refreshSkills(),reloadMcp:i.reloadMcp,mcpOauth:i.mcpOauth,envs:i.envs,envCount:i.envCount,envMsg:i.envMsg,envRepoLine:i.envRepoLine,envRepoBar:i.envRepoBar,envRepoMsg:i.envRepoMsg,envSelect:i.envSelect,setEnvSelect:i.setEnvSelect,refreshEnvs:()=>void i.refreshEnvs(),createEnv:i.createEnv,archiveEnv:i.archiveEnv,saveEnvRepo:i.saveEnvRepo,models:i.models,modelCustomVisible:i.modelCustomVisible,tasks:r.tasks,taskCountText:r.taskCountText,taskError:r.taskError,refreshTasks:()=>void r.refreshTasks(void 0,m.current),statusFilter:r.statusFilter,setStatusFilter:r.setStatusFilter,executorFilter:r.executorFilter,setExecutorFilter:r.setExecutorFilter,searchText:r.searchText,setSearchText:r.setSearchText,filteredTasks:r.filteredTasks,currentTask:x.currentTask,detailBody:x.detailBody,actionMsg:x.actionMsg,actionReasons:x.actionReasons,showDetail:V=>void x.showDetail(V),doAction:x.doAction,taskCost:x.taskCost,costBox:x.costBox,forkVisible:x.forkVisible,setForkVisible:x.setForkVisible,forkTask:x.forkTask,forkMsg:x.forkMsg,coordChildren:x.coordChildren,coordText:"",agents:x.agents,agentsNote:x.agentsNote,reviews:x.reviews,reviewMsg:x.reviewMsg,reviewError:x.reviewError,refreshReviews:x.refreshReviews,postReview:x.postReview,submitFindings:x.submitFindings,traceEntries:x.traceEntries,traceNote:x.traceNote,traceDone:x.traceDone,traceKind:x.traceKind,setTraceKind:x.setTraceKind,downloadTrace:x.downloadTrace,traceMsg:x.traceMsg,sendChatMessage:x.sendChatMessage,chatMsg:x.chatMsg,chatHistory:x.chatHistory,followups:x.followups,approvals:x.approvals,approvalMsg:x.approvalMsg,refreshApprovals:x.refreshApprovals,decideApproval:x.decideApproval,peerMessages:x.peerMessages,peerMsg:x.peerMsg,postPeer:x.postPeer,automations:_.automations,autoMsg:_.autoMsg,refreshAutomations:()=>void _.refreshAutomations(),createAutomation:_.createAutomation,cancelAutomation:_.cancelAutomation,triage:_.triage,triageError:_.triageError,refreshTriage:()=>void _.refreshTriage(),threadText:x.threadText,threadGateNote:x.threadGateNote,threadMsg:x.threadMsg,threadList:x.threadList,threadAction:x.threadAction,dispatch:async(V,dt)=>{const Ot=await r.dispatch(V,dt);return r.refreshTasks(m.current),Ot},dispatchMsg:"",refreshAll:lt,refreshSlow:at,refreshStamp:G}}function cu({label:i,value:r,sub:m}){return s.jsxs("div",{className:"dash-card data-card",children:[s.jsx("div",{className:"dash-card-label",children:i}),s.jsx("div",{className:"dash-card-value",children:r}),s.jsx("div",{className:"muted",children:m})]})}function ng(){const i=Mt(),r=i.healthText==="未加载"?"未加载":i.healthText.includes("worker_ok=true")?"正常":i.healthText.includes("worker_ok=false")?"异常":i.healthText.includes("加载失败")?"加载失败":"未知",m=i.quotaText.match(/剩余 \$([0-9.]+)/),o=i.quotaText.includes("加载失败")?"加载失败":i.quotaText.includes("未填 key")||i.quotaText==="未加载"?"未加载":m?"$"+m[1]:"配额",_=["running","completed","failed","queued","merged","interrupted"].map(b=>i.tasks.filter(B=>B.status===b).length).map((b,B)=>["running","completed","failed","queued","merged","interrupted"][B]+" "+b).join(" | "),C=i.projects.find(b=>b.id===i.projectId),N=i.taskError?{value:"加载失败",sub:i.taskError}:i.projectId?{value:String(i.tasks.length),sub:i.taskCountText+" | "+_+(C?" | "+C.name:"")}:{value:"先选项目",sub:i.projectMsg||"项目加载后自动选第一个"};let x;if(i.workersError)x={value:"加载失败",sub:i.workersError};else if(i.workers===null)x={value:i.workersSummary||"未加载",sub:"完整 worker 清单仅全局管理员可见"};else{const b=i.workers.filter(B=>{if(B.alive!==void 0&&B.alive!==null)return!!B.alive;const lt=Qh(B).age;return lt!==null&<<=120}).length;x={value:b+" 在线 / "+i.workers.length,sub:i.workers.length-b+" 离线"}}const G=i.projectMsg.includes("加载失败")?{value:"加载失败",sub:i.projectMsg}:{value:i.projects.length+" 个",sub:C?"当前项目:"+C.name:"未选项目(加载后自动选第一个)"},U=[i.envMsg,i.memberError,i.skillError].filter(b=>b&&b.includes("失败")),Q=i.projectId?U.length?{value:"部分加载失败",sub:U.join(" | ")}:{value:i.envs.length+" 个环境",sub:i.members.length+" 成员 | "+i.skills.length+" 技能 | "+i.apps.length+" 应用 | "+i.mcpServers.length+" MCP"}:{value:"先选项目",sub:"选项目后显示环境 / 成员 / 技能计数"};return s.jsxs("section",{className:"dash-cards","aria-label":"数据卡片",children:[s.jsx(cu,{label:"健康",value:r,sub:i.healthText}),s.jsx(cu,{label:"配额",value:o,sub:i.quotaText}),s.jsx(cu,{label:"任务",value:N.value,sub:N.sub}),s.jsx(cu,{label:"Workers",value:x.value,sub:x.sub}),s.jsx(cu,{label:"项目",value:G.value,sub:G.sub}),s.jsx(cu,{label:"项目数据",value:Q.value,sub:Q.sub})]})}function Ve({id:i,className:r,title:m,children:o}){return s.jsxs("section",{id:i,className:"card"+(r?" "+r:""),children:[m?s.jsx("h2",{children:m}):null,o]})}function Dt({children:i}){return s.jsx("div",{className:"bar",children:i})}function Dl({items:i,empty:r}){return i.length?s.jsx("ul",{className:"data-list",children:i.map((m,o)=>s.jsx("li",{children:m},o))}):s.jsx("div",{className:"muted",children:r||"(暂无)"})}function ru({children:i}){return s.jsx("ul",{className:"data-list",children:i})}function ug(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState(!1),[x,G]=v.useState(!1),[U,Q]=v.useState(!1),[b,B]=v.useState("docker"),[lt,at]=v.useState(""),[I,V]=v.useState(""),[dt,Ot]=v.useState(""),[te,nt]=v.useState(""),[Xt,ee]=v.useState(""),[ct,yt]=v.useState(""),[le,de]=v.useState(""),Kt=v.useRef(null),Ft=v.useRef(null),Wt=v.useRef(null),[tl,mt]=v.useState("");async function Y(){var Oe,ze,y;if(mt(""),!i.projectId){mt("先选项目");return}if(!r.trim()){mt("prompt 必填");return}const A={project_id:i.projectId,prompt:r.trim()};i.envSelect&&(A.environment_id=i.envSelect),b&&(A.executor=b);const et=I.trim()||lt;et&&(A.model=et),dt&&(A.effort=dt);const Tt=ct.trim()||Xt;if(Tt&&(A.child_model=Tt),le&&(A.child_effort=le),te&&(A.approval=te),U){if(te==="full"){mt("计划模式不能与完全访问同用");return}if(C||x){mt("计划模式不能与 goal 模式同用");return}A.plan=1}x?(A.goal_mode=1,A.no_time_limit=1):C&&(A.goal_mode=1);const gt=o.trim();if(gt){try{A.coordinator_parts=JSON.parse(gt)}catch{mt("协调员子任务 JSON 解析失败");return}if(!Array.isArray(A.coordinator_parts)){mt("协调员子任务必须是数组");return}if(C||x||U){mt("协调员任务不能与 goal/计划模式同用:协调员任务本身不跑模型回合,请取消 goal/计划勾选,或清空协调员 JSON");return}}const ie=Fy(((Oe=Kt.current)==null?void 0:Oe.files)||null,((ze=Ft.current)==null?void 0:ze.files)||null,((y=Wt.current)==null?void 0:y.files)||null);try{const R=await i.dispatch(A,ie);mt(R),m(""),_(""),Kt.current&&(Kt.current.value=""),Ft.current&&(Ft.current.value=""),Wt.current&&(Wt.current.value="")}catch(R){mt("提交失败:"+((R==null?void 0:R.message)||String(R)))}}return s.jsxs(Ve,{id:"nav-newtask",className:"composer",title:"新建任务",children:[s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"环境",value:i.envSelect,onChange:A=>i.setEnvSelect(A.target.value),children:[s.jsx("option",{value:"",children:"环境:不指定(走项目仓库)"}),i.envs.map(A=>s.jsxs("option",{value:A.id,disabled:A.status!=="ready",children:[A.name,"(",A.status,")"]},A.id))]}),s.jsxs("select",{"aria-label":"执行器",value:b,onChange:A=>B(A.target.value),children:[s.jsx("option",{value:"docker",children:"docker(默认,多用户下隔离最强)"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"cloud",children:"cloud"})]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:C,onChange:A=>N(A.target.checked)})," goal 模式"]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:x,onChange:A=>G(A.target.checked)})," goal 模式无敌版"]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:U,onChange:A=>Q(A.target.checked)})," 计划模式(只读)"]})]}),s.jsx("textarea",{className:"prompt stacked",placeholder:"任务 prompt(必填)",value:r,onChange:A=>m(A.target.value)}),s.jsx("textarea",{className:"coord stacked",placeholder:"协调员子任务 JSON(可选),留空为普通任务",value:o,onChange:A=>_(A.target.value)}),s.jsxs("div",{className:"muted",children:["协调员格式:[","{",'"name":"后端","prompt":"做后端"',"}",",","{",'"name":"前端","prompt":"做前端"',"}","];提交后 worker 并行建子任务、等齐、合流汇总。不能与 goal/计划模式同用。协调员与 goal/计划互斥:勾了 goal 或计划模式时不要填协调员 JSON,提交前会校验并拦截。子任务费用记父任务创建人账;父任务创建时按分工数预留配额,余额不足时整个父任务被挡下。"]}),s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"模型",value:lt,onChange:A=>at(A.target.value),children:[s.jsx("option",{value:"",children:"模型:默认(跟随配置)"}),i.models.map(A=>s.jsx("option",{value:A,children:A},A))]}),i.modelCustomVisible?s.jsx("input",{type:"text",placeholder:"手动输入模型(中转列表取不到时用)",value:I,onChange:A=>V(A.target.value)}):null,s.jsxs("select",{"aria-label":"推理强度",value:dt,onChange:A=>Ot(A.target.value),children:[s.jsx("option",{value:"",children:"推理强度:默认(跟随配置)"}),Yh.map(A=>s.jsx("option",{value:A,children:A},A))]}),s.jsxs("select",{"aria-label":"权限",value:te,onChange:A=>nt(A.target.value),children:[s.jsx("option",{value:"",children:"权限:默认(跟随配置)"}),s.jsx("option",{value:"ask",children:"请求批准"}),s.jsx("option",{value:"auto",children:"帮我批准"}),s.jsx("option",{value:"full",children:"完全访问"})]})]}),s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"子任务模型",value:Xt,onChange:A=>ee(A.target.value),children:[s.jsx("option",{value:"",children:"子任务模型:跟随本任务模型"}),i.models.map(A=>s.jsx("option",{value:A,children:A},A))]}),s.jsx("input",{type:"text",placeholder:"子任务模型手动输入(中转列表里没有时填,如 gpt-6-luna;留空=跟随本任务模型)",value:ct,onChange:A=>yt(A.target.value)}),s.jsxs("select",{"aria-label":"子任务强度",value:le,onChange:A=>de(A.target.value),children:[s.jsx("option",{value:"",children:"子任务强度:跟随本任务强度"}),Yh.map(A=>s.jsx("option",{value:A,children:A},A))]})]}),s.jsx("div",{className:"muted",children:"子任务模型/强度是派生默认:本任务用 marker task-create 或协调员分工派生的子任务,未显式写模型/强度时用它;块/分工里显式写了则覆盖它。也可以不在这里填、直接在 prompt 里写“子任务用 gpt-6-luna max”,建任务时服务端会解析成同一对字段(任务详情里可核对)。"}),C?s.jsx("div",{className:"muted",children:"goal 模式:输入框内容即目标,不需要专用 prompt 与验收命令;不限轮次,模型确认达成后在回复末尾输出“目标已达成”即结束,未达成会一直运行,可用取消停止。"}):null,x?s.jsx("div",{className:"muted",children:"goal 模式无敌版:goal 模式 + 任务不限时(去掉 worker/docker 总超时;单轮 600 秒护栏还在,不限的是任务总时长与总轮次)。服务端默认的自动续跑与断点镜像同时生效。"}):null,s.jsxs(Dt,{children:[s.jsx("span",{className:"muted",children:"附件(放进任务工作区,图片与普通文件不区分):"}),s.jsx("input",{ref:Kt,type:"file",multiple:!0,title:"文件"}),s.jsx("input",{ref:Ft,type:"file",multiple:!0,title:"文件夹",webkitdirectory:""}),s.jsx("input",{ref:Wt,type:"file",accept:"image/*",multiple:!0,title:"图片"})]}),s.jsxs(Dt,{children:[s.jsx("button",{className:"seal",onClick:Y,children:"提交任务"}),s.jsx("span",{className:"muted",children:tl||i.dispatchMsg})]})]})}function kh(i){const r=(i.prompt||"").trim();return r?[...r][0]:i.id?[...i.id][0]:"?"}function zc(i){const r=Math.max(0,Math.floor(i));if(r<60)return r+"秒";if(r<3600){const _=Math.floor(r/60),C=r%60;return C?_+"分"+C+"秒":_+"分"}if(r<86400){const _=Math.floor(r/3600),C=Math.floor(r%3600/60);return C?_+"小时"+C+"分":_+"小时"}const m=Math.floor(r/86400),o=Math.floor(r%86400/3600);return o?m+"天"+o+"小时":m+"天"}function fu(i){if(i==null)return null;const r=Number(i);return Number.isFinite(r)?r:null}function Xh(i){const r=Date.now()/1e3,m=fu(i.started_at),o=fu(i.finished_at),_=fu(i.created_at);return m!==null&&o!==null&&o>=m?[zc(o-m),"总耗时:开始→结束(末次认领的执行时长)"]:m!==null&&i.status==="running"?["进行中 "+zc(r-m),"总耗时:进行中,已用时长从开始算起,随刷新更新"]:_!==null&&o!==null&&o>=_?[zc(o-_),"总耗时:创建→完成(含排队等待;无开始时间时的兜底口径)"]:_!==null&&(i.status==="queued"||i.status==="running")?[(i.status==="queued"?"排队中 ":"进行中 ")+zc(r-_),"总耗时:从创建算起的已用时长(无开始时间时的兜底口径)"]:["—","总耗时:无可用时间戳"]}function Vh(i){const r=fu(i.total_tokens);if(r!==null)return[r.toLocaleString()+" token","token:服务端 total_tokens"];const m=fu(i.actual_tokens),o=fu(i.estimated_tokens);return m!==null||o!==null?[((m||0)+(o||0)).toLocaleString()+" token","token:actual + estimated 分项加总"]:["token —","token:本任务对象未带 token 字段;单任务真数在详情的成本里可查,不逐个调成本接口、不编造"]}function ig({onNew:i}){const r=Mt();return s.jsxs("div",{children:[s.jsxs("div",{className:"search-box",children:[s.jsxs("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round","aria-hidden":"true",children:[s.jsx("circle",{cx:"11",cy:"11",r:"7"}),s.jsx("path",{d:"M21 21l-4.3-4.3"})]}),s.jsx("input",{type:"text",placeholder:"搜索","aria-label":"搜索任务",value:r.searchText,onChange:m=>r.setSearchText(m.target.value)})]}),s.jsx("div",{className:"bar",children:s.jsxs("select",{"aria-label":"项目",value:r.projectId,onChange:m=>r.selectProject(m.target.value),children:[r.projects.length===0?s.jsx("option",{value:"",children:"(先加载项目)"}):null,r.projects.map(m=>s.jsxs("option",{value:m.id,children:[m.name," (",Me(m.id),")"]},m.id))]})}),s.jsxs("div",{className:"list-section-head",children:[s.jsx("span",{children:"主要聊天"}),s.jsx("button",{type:"button","aria-label":"派发新任务",title:"派发新任务",onClick:i,children:"+"})]}),s.jsxs("div",{className:"bar",children:[s.jsxs("select",{"aria-label":"状态筛选",value:r.statusFilter,onChange:m=>r.setStatusFilter(m.target.value),children:[s.jsx("option",{value:"",children:"状态:全部"}),["queued","running","completed","failed","interrupted","merged","merge-failed"].map(m=>s.jsx("option",{value:m,children:m},m))]}),s.jsxs("select",{"aria-label":"执行器筛选",value:r.executorFilter,onChange:m=>r.setExecutorFilter(m.target.value),children:[s.jsx("option",{value:"",children:"执行器:全部"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"docker",children:"docker"}),s.jsx("option",{value:"cloud",children:"cloud"})]})]}),s.jsxs("div",{className:"bar",children:[s.jsx("button",{onClick:r.refreshTasks,children:"刷新"}),s.jsx("span",{className:"muted",children:r.taskCountText})]}),r.taskError?s.jsx("div",{className:"err",children:r.taskError}):r.projectId?r.filteredTasks.length===0?s.jsx("div",{className:"muted",children:r.tasks.length?"没有符合筛选条件的任务":"该项目暂无任务"}):s.jsx("ul",{className:"issue-list",children:r.filteredTasks.slice().reverse().map(m=>{var G;const[o,_]=Xh(m),[C,N]=Vh(m),x=kh(m);return s.jsxs("li",{className:"issue-item"+(((G=r.currentTask)==null?void 0:G.id)===m.id?" selected":""),onClick:()=>r.showDetail(m.id),children:[s.jsx("span",{className:"issue-state st-"+m.status,"aria-hidden":"true"}),s.jsx("span",{className:"issue-first",title:"任务首字:"+x,"aria-hidden":"true",children:x}),s.jsxs("span",{style:{flex:1,minWidth:0},children:[s.jsxs("div",{className:"issue-title",children:[m.plan?"[计划] ":"",m.forked_from?"[分支] ":"",m.coordinator_parts?"[协调] ":"",m.parent_task_id?"[协调子任务] ":"",String(m.prompt||Me(m.id)).slice(0,60)]}),s.jsxs("div",{className:"issue-meta",children:[Me(m.id)," · ",s.jsx("span",{className:"st-"+m.status,children:m.status})," · ",m.executor||"",m.updated_at?" · "+new Date(m.updated_at*1e3).toLocaleString():""," · ",s.jsxs("span",{title:_,children:["耗时 ",o]})," · ",s.jsx("span",{title:N,children:C})]})]})]},m.id)})}):s.jsx("div",{className:"muted",children:"先选项目"})]})}function cg(i){const r=v.useRef(null),[m,o]=v.useState(!0),_=v.useRef(!0),C=()=>{const N=r.current;if(!N)return;const x=N.scrollHeight-N.scrollTop-N.clientHeight<80;_.current=x,o(x)};return v.useEffect(()=>{_.current&&r.current&&(r.current.scrollTop=r.current.scrollHeight)},[i]),{ref:r,following:m,onScroll:C}}function sg({msg:i}){if(i.role==="status")return s.jsx("div",{className:"chat-status",children:i.text});const r=i.label||(i.role==="user"?"用户":i.role==="assistant"?"助手":"工具");return s.jsxs("div",{className:"gh-comment "+i.role,children:[s.jsx("div",{className:"gh-comment-header",children:s.jsx("span",{className:"gh-comment-author",children:r})}),s.jsx("div",{className:"gh-comment-body",children:i.text})]})}function Lh({messages:i,empty:r}){const{ref:m,following:o,onScroll:_}=cg(i.length);return s.jsxs("div",{className:"chat-list",ref:m,onScroll:_,children:[i.length===0?s.jsx("div",{className:"muted",children:r||"(暂无消息)"}):i.map(C=>s.jsx(sg,{msg:C},C.id)),!o&&i.length>0?s.jsx("button",{className:"chat-follow",onClick:()=>{m.current&&(m.current.scrollTop=m.current.scrollHeight)},children:"回到最新 ↓"}):null]})}function fg({onSend:i,disabled:r,placeholder:m}){const[o,_]=v.useState(""),C=()=>{const N=o.trim();!N||r||(i(N),_(""))};return s.jsxs("div",{className:"gh-comment-box",children:[s.jsx("textarea",{"aria-label":"会话输入",rows:3,placeholder:m||"消息",value:o,disabled:r,onChange:N=>_(N.target.value),onKeyDown:N=>{N.key==="Enter"&&!N.shiftKey&&(N.preventDefault(),C())}}),s.jsx("div",{className:"gh-comment-footer",children:s.jsx("button",{type:"button",className:"primary","aria-label":"发送",disabled:r||!o.trim(),onClick:C,children:"发送"})})]})}function Zh(i,r){const m=i.id||"trace-"+r;if(i.kind==="message")return{id:m,role:"assistant",text:(i.phase?"["+i.phase+"] ":"")+(i.text||""),label:"助手"};if(i.kind==="exec"||i.kind==="file"||i.kind==="tool"||i.kind==="call"){const o=i.kind==="exec"?"命令":i.kind==="file"?"文件":i.kind==="tool"?"工具":"调用";return{id:m,role:"tool",text:or(i),label:o}}return i.kind==="plan"?{id:m,role:"status",text:i.text||""}:i.kind==="reasoning"?{id:m,role:"status",text:"思考:"+(i.summary||"")}:i.kind==="agent-start"?{id:m,role:"status",text:"子代理开始:"+(i.name||"")+(i.prompt?"("+i.prompt+")":"")}:i.kind==="agent-done"?{id:m,role:"status",text:"子代理结束:"+(i.name||"")+" "+(i.status||"")}:{id:m,role:"status",text:or(i)}}function rg(){const i=Mt(),r=v.useMemo(()=>{const m=i.currentTask,o=m&&m.prompt?[{id:"task-prompt",role:"user",text:m.prompt}]:[],C=(i.traceKind?i.traceEntries.filter(x=>x.kind===i.traceKind):i.traceEntries).map((x,G)=>Zh(x,G)),N=i.traceDone?[{id:"trace-done",role:"status",text:"链路已结束("+i.traceDone+")"}]:[];return[...o,...C,...N]},[i.currentTask,i.traceEntries,i.traceKind,i.traceDone]);return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"muted",children:"实时链路"}),s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"链路类型",value:i.traceKind,onChange:m=>i.setTraceKind(m.target.value),children:[s.jsx("option",{value:"",children:"链路类型:全部"}),["exec","file","call","tool","message","reasoning","plan","agent-start","agent-done"].map(m=>s.jsx("option",{value:m,children:m==="exec"?"命令":m==="file"?"文件":m==="call"?"调用":m==="tool"?"工具":m==="message"?"消息":m==="reasoning"?"思考":m==="plan"?"计划":"子代理"},m))]}),s.jsx("button",{onClick:i.downloadTrace,children:"下载完整链路"}),s.jsx("span",{className:"muted",children:i.traceMsg})]}),i.traceNote?s.jsx("div",{children:s.jsx("span",{className:"err",children:i.traceNote})}):null,s.jsx("div",{className:"chat-column",children:s.jsx(Lh,{messages:r,empty:"(暂无链路条目)"})}),s.jsx("div",{className:"muted",children:"对话时间线:首条是本任务 prompt(用户);助手回复来自 message 条目,命令/文件/工具/调用是工具评论框,计划/思考/子代理开始结束是时间线上的状态文字。流式进行中时新条目实时追加;你在底部时自动跟随,往上翻时暂停跟随,点“回到最新”恢复。"})]})}function og(){const i=Mt(),r=i.currentTask,m=v.useMemo(()=>{if(!r)return[];if(i.chatHistory)return i.chatHistory.messages.map(b=>({id:b.id,role:b.role,text:b.text,label:b.label}));const G=r.prompt?[{id:"task-prompt",role:"user",text:r.prompt}]:[],U=i.traceEntries.filter(b=>b.kind==="message").map((b,B)=>Zh(b,B)),Q=i.followups.map((b,B)=>({id:"followup-"+B,role:"user",text:String(b.body||""),label:"后续消息"}));return[...G,...U,...Q]},[r,i.chatHistory,i.traceEntries,i.followups]);if(!r)return s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示继续会话"});const o=su.includes(r.status),_=["queued","running"].includes(r.status),C=o||_,N=o?"终态任务:发送走继续接口(同一会话再跑一轮)":_?"运行中/排队中:发送走后续消息直接发送(跑完当前轮后优先执行)":"merged/merge-failed 任务不可继续,也不可发后续消息",x=i.chatHistory?i.chatHistory.legacy_continue_count??null:null;return s.jsxs("div",{className:"chat-column",children:[x!==null&&x>0?s.jsxs("div",{className:"muted",children:["此前有 ",x," 条继续消息发生在持久化之前,未入库,上面历史不完整;部署后新发的继续消息会正常显示。"]}):null,i.chatHistory&&i.chatHistory.trace_note?s.jsx("div",{className:"muted",children:i.chatHistory.trace_note}):null,s.jsx(Lh,{messages:m,empty:"(暂无会话消息)"}),s.jsx(fg,{disabled:!C,placeholder:"消息",onSend:G=>void i.sendChatMessage(G)}),s.jsxs("div",{className:"muted",children:[N,"。",i.chatMsg]})]})}function dg(){return Mt().currentTask?s.jsxs("div",{className:"conversation",children:[s.jsx(rg,{}),s.jsx("div",{className:"conv-divider"}),s.jsx(og,{})]}):s.jsx("div",{className:"conversation",children:s.jsx("div",{className:"muted",children:"在任务列表里点一条任务,对话和详情就切到该任务;也可以在上面派发一个新任务。"})})}function mg(){const i=Mt(),r=i.currentTask,[m,o]=v.useState("");if(!r)return null;const _=su.includes(r.status),C=["failed","interrupted","merge-failed"].includes(r.status);return s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("button",{disabled:!C,title:C?"":"仅 failed/interrupted/merge-failed 可重试",onClick:()=>i.doAction("retry"),children:"重试"}),s.jsx("button",{className:"danger",disabled:_,title:_?"终态任务不可取消":"",onClick:()=>i.doAction("cancel"),children:"取消"}),s.jsx("button",{disabled:r.status!=="completed",title:r.status!=="completed"?"仅 completed 可合并":"",onClick:()=>i.doAction("merge"),children:"合并(completed → merged)"}),s.jsx("button",{disabled:r.status!=="merged",title:r.status!=="merged"?"仅 merged 可提 PR":"",onClick:()=>i.doAction("pr"),children:"提 PR(须 merged)"}),_?s.jsx("button",{onClick:()=>i.setForkVisible(!0),children:"分支"}):null,s.jsx("button",{onClick:i.taskCost,children:"查成本"}),s.jsxs("span",{className:"muted",children:[i.actionMsg," ",i.actionReasons]})]}),i.forkVisible?s.jsxs("div",{children:[s.jsx("input",{type:"text",placeholder:"分支首轮消息(必填,带历史的新会话)",style:{width:"100%",boxSizing:"border-box",margin:"6px 0"},value:m,onChange:N=>o(N.target.value)}),s.jsxs(Dt,{children:[s.jsx("button",{className:"seal",onClick:async()=>{await i.forkTask(m),o("")},children:"创建分支任务"}),s.jsx("span",{className:"muted",children:i.forkMsg})]})]}):null]})}function hg(){const i=Mt(),[r,m]=v.useState("uncommittedChanges"),[o,_]=v.useState(""),[C,N]=v.useState(""),[x,G]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("h3",{children:"评审队列"}),s.jsxs("select",{"aria-label":"评审目标",value:r,onChange:U=>m(U.target.value),children:[s.jsx("option",{value:"uncommittedChanges",children:"未提交改动(工作区)"}),s.jsx("option",{value:"baseBranch",children:"与分支的差异"}),s.jsx("option",{value:"commit",children:"指定提交"}),s.jsx("option",{value:"custom",children:"自定义评审指令"})]}),s.jsx("input",{className:"stacked",placeholder:"与分支的差异用:分支名(如 main)",style:{width:"100%"},value:o,onChange:U=>_(U.target.value)}),s.jsx("input",{className:"stacked",placeholder:"指定提交用:提交 sha",style:{width:"100%"},value:C,onChange:U=>N(U.target.value)}),s.jsx("textarea",{placeholder:"自定义评审指令用:评审指令正文",value:x,onChange:U=>G(U.target.value)}),s.jsxs(Dt,{children:[s.jsx("button",{className:"primary",onClick:()=>void i.postReview({target_type:r,branch:o.trim()||void 0,sha:C.trim()||void 0,instructions:x.trim()||void 0}),children:"登记评审需求"}),s.jsx("button",{onClick:i.refreshReviews,children:"刷新队列"}),s.jsx("span",{className:"muted",children:i.reviewMsg})]}),s.jsx("div",{className:"muted",children:"本基线只登记评审需求(requested),不自动跑评审;评审是否执行、结果如何,以评审队列里的记录为准。"}),i.reviewError?s.jsx("div",{className:"muted",children:i.reviewError}):i.reviews.length===0?s.jsx("div",{className:"muted",children:"点任务行查看详情后,点“刷新队列”查看评审记录"}):s.jsx(ru,{children:i.reviews.map(U=>{let Q=U.target_type||"";return U.branch&&(Q+=":"+U.branch),U.sha&&(Q+=":"+String(U.sha).slice(0,12)),U.instructions&&(Q+=":"+String(U.instructions).slice(0,80)),s.jsxs("li",{children:[s.jsxs("span",{className:"row-main",children:[s.jsx("b",{children:"评审"})," ",Me(U.id)," | ",Q," | ",s.jsx("span",{className:"st-"+(U.status||""),children:U.status}),U.created_at?" | "+Xa(U.created_at):"",s.jsx("br",{}),U.findings?String(U.findings).slice(0,1e3):s.jsx("span",{className:"muted",children:"(暂无 findings:评审尚未执行或尚未写回)"})]}),s.jsx("button",{onClick:()=>i.submitFindings(U.id),children:"写 findings"})]},U.id)})})]})}function vg(){const i=Mt();return i.currentTask?i.currentTask.coordinator_parts?i.coordChildren.length===0?s.jsx("div",{className:"muted",children:"(子任务尚未创建)"}):s.jsx(ru,{children:i.coordChildren.map(r=>s.jsx("li",{children:s.jsxs("span",{className:"row-main",children:["分工 ",s.jsx("b",{children:r.coordinator_part||""})," | 状态 ",s.jsx("span",{className:"st-"+r.status,children:r.status})," | ",Me(r.id)," | ",String(r.prompt||"").slice(0,60)]})},r.id))}):s.jsx("div",{className:"muted",children:"(非协调员任务)"}):s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示协调员的子任务"})}function yg(){const i=Mt();if(!i.currentTask)return s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示子代理链路"});if(i.agents.length===0)return s.jsxs("div",{className:"muted",children:["(暂无子代理)",i.agentsNote?s.jsx("span",{className:"err",children:i.agentsNote}):null]});const r={main:"主任务",delegate:"委派子任务",model:"模型子代理"},m={running:"进行中",completed:"已完成",failed:"失败",interrupted:"已中断",unknown:"未知"};return s.jsx(ru,{children:i.agents.map((o,_)=>s.jsx("li",{children:s.jsxs("span",{className:"row-main",children:[s.jsxs("b",{children:[r[o.kind||""]||o.kind||"",":"]}),o.name||""," ",s.jsx("span",{className:"st-"+(o.status||""),children:m[o.status||""]||o.status||"?"})," | 过程调用 "+(o.calls?o.calls.length:0)+" 条",o.updated_ts?" | 最近活动 "+Xa(o.updated_ts/1e3):"",o.prompt?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsxs("span",{className:"muted",children:["任务:",o.prompt]})]}):null,o.calls&&o.calls.length?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),o.calls.slice(-50).map((C,N)=>s.jsx("div",{children:or(C)},N))]}):s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsx("span",{className:"muted",children:"(暂无过程调用)"})]})]})},_))})}function gg(){const i=Mt();return s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.refreshApprovals,children:"刷新审批队列"}),s.jsx("span",{className:"muted",children:i.approvalMsg})]}),s.jsx("div",{className:"muted",children:"待审批项需人工点记录允许或记录拒绝;超时默认拒绝。当前版本只留回执,不拦截实时行为(实时请求的事前拦截待 host 接入后生效,在此之前实时行为不变)。"}),s.jsx(Dl,{empty:"(暂无审批项)",items:i.approvals.map(r=>s.jsxs("span",{className:"row-main",children:["[",r.kind,"|",r.status,"] ",r.summary,["approved","denied","expired"].includes(r.status||"")?"|回执:"+(r.decision||r.status)+" by "+String(r.decided_by||"").slice(0,8)+" "+Xa(r.decided_at):"",r.status==="pending"?s.jsxs(s.Fragment,{children:[" ",s.jsx("button",{onClick:()=>i.decideApproval(r.id,"approved"),children:"记录允许"})," ",s.jsx("button",{onClick:()=>i.decideApproval(r.id,"denied"),children:"记录拒绝"})]}):null]},r.id))})]})}function pg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("input",{placeholder:"目标任务 id(与本任务同项目;对方运行中排队执行、已终态则续跑复活,绝不打断当前轮)",style:{width:"100%"},value:r,onChange:C=>m(C.target.value)}),s.jsx("textarea",{placeholder:"消息正文(以本任务名义发出;对方 agent 会看到发送方任务 id,可照此回消息)",value:o,onChange:C=>_(C.target.value)}),s.jsxs(Dt,{children:[s.jsx("button",{onClick:async()=>{await i.postPeer("queued",r,o),_("")},children:"排队发给对方"}),s.jsx("button",{className:"primary",onClick:async()=>{await i.postPeer("direct",r,o),_("")},children:"直接发送"}),s.jsx("span",{className:"muted",children:i.peerMsg})]}),s.jsx(Dl,{empty:"(本任务尚未发出任务间消息)",items:i.peerMessages.map((C,N)=>s.jsxs("span",{className:"row-main",children:["[发给 ",String(C.task_id).slice(0,8),"|",C.mode,"|",C.status,"] ",String(C.body||"").slice(0,120)]},N))})]})}function Sg(){const i=Mt(),[r,m]=v.useState(""),o=i.currentTask?["completed","failed","interrupted"].includes(i.currentTask.status):!1;return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"muted",children:i.threadText||"点任务行查看详情后,这里显示线程元数据"}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"新线程名",value:r,onChange:_=>m(_.target.value)}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("rename",r),children:"重命名"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("archive",""),children:"归档"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("unarchive",""),children:"取消归档"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("compact",""),children:"压缩"}),s.jsx("span",{className:"muted",children:i.threadGateNote}),s.jsx("span",{className:"muted",children:i.threadMsg})]}),s.jsx(Dl,{empty:"暂无其他线程",items:i.threadList.map((_,C)=>s.jsxs("span",{className:"row-main",children:[_.name||_.thread_name||_.id||""," [",_.id||"","]",_.archived?" [已归档]":"",_.cwd?" "+_.cwd:""]},C))}),s.jsx("div",{className:"muted",children:"限制:Docker/异机任务线程操作一律 409;merged/merge-failed 不可改;turn/steer 与 review/start 不在本批。"})]})}function bg(){const i=Mt(),r=i.currentTask;if(!r)return s.jsx(Ve,{id:"nav-detail",title:"任务详情",children:s.jsx("div",{className:"muted",children:"点任务行查看详情"})});const[m,o]=Xh(r),[_,C]=Vh(r),N=kh(r);return s.jsxs(Ve,{id:"nav-detail",title:"任务详情",children:[s.jsxs("div",{children:["状态 ",s.jsx("b",{className:"st-"+r.status,children:r.status}),"(",Vy[r.status]||"未知状态",")",s.jsx("br",{}),s.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6},children:[s.jsx("span",{className:"issue-first",title:"任务首字:"+N,"aria-hidden":"true",children:N}),s.jsxs("span",{title:o,children:["耗时 ",m]}),s.jsx("span",{children:" · "}),s.jsx("span",{title:C,children:_})]}),s.jsx("br",{}),"任务 ",r.id," | turn ",Me(r.turn_id)," | root turn ",Me(r.root_turn_id),s.jsx("br",{}),"executor ",r.executor||""," | 主机 ",r.worktree_host||"",s.jsx("br",{}),"模型 ",r.model||"默认"," | 强度 ",r.effort||"默认",r.child_model||r.child_effort?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"子任务默认 ",(r.child_model||"跟随本任务")+" / "+(r.child_effort||"跟随本任务")]}):null,s.jsx("br",{}),"权限 ",r.approval||"默认"," | 项目 ",Me(r.project_id),s.jsx("br",{}),"更新 ",Xa(r.updated_at),r.plan?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"计划模式(只读)"]}):null,r.forked_from?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"分支自 ",Me(r.forked_from)]}):null,r.goal_mode?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),r.no_time_limit?"goal 模式无敌版(不限时)":"goal 模式(不限轮次,模型宣告完成)"]}):r.verify_command?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"goal 模式(旧语义,验收命令)"]}):null,r.coordinator_parts?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"协调员:",r.coordinator_parts.length," 个子任务(",r.coordinator_parts.map(x=>x.name).join("、"),")"]}):null,r.parent_task_id?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"协调子任务,父任务 ",Me(r.parent_task_id),r.coordinator_part?"("+r.coordinator_part+")":""]}):null,r.attachments&&r.attachments.length?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"附件:",r.attachments.join("、")]}):null,r.pr_url?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsxs("a",{href:r.pr_url,target:"_blank",rel:"noopener noreferrer",children:["PR #",r.pr_number]})]}):null,s.jsx("br",{}),"prompt:",r.prompt||""]}),s.jsx(mg,{}),s.jsx("pre",{children:i.detailBody||"(暂无 result/error 输出)"}),i.costBox?s.jsx("pre",{children:i.costBox}):null,s.jsx("h3",{children:"协调子任务"}),s.jsx(vg,{}),s.jsx("h3",{children:"子代理链路"}),s.jsx(yg,{}),s.jsx("h3",{children:"评审队列"}),s.jsx(hg,{}),s.jsx("h3",{children:"运行时审批队列"}),s.jsx(gg,{}),s.jsx("h3",{children:"给其他任务发消息"}),s.jsx(pg,{}),s.jsx("h3",{children:"线程"}),s.jsx(Sg,{})]})}function xg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState([]),[x,G]=v.useState(null),[U,Q]=v.useState(!1),[b,B]=v.useState(""),[lt,at]=v.useState(""),I=v.useCallback(async()=>{if(!i.keySaved){N([]);return}try{const nt=await tt($.userKeys);N(nt.keys||[]),at("")}catch(nt){at(nt instanceof Error?nt.message:"加载 key 列表失败")}},[i.keySaved]);v.useEffect(()=>{I()},[I]);const V=async()=>{B(""),at(""),Q(!1);try{const nt=await tt($.userKeys,"POST",{label:o.trim()||"api-key"});G(nt),_(""),B("新 key 已生成,只显示一次:复制后请妥善保存。"),await I()}catch(nt){at(nt instanceof Error?nt.message:"生成 key 失败")}},dt=async()=>{if(x)try{await navigator.clipboard.writeText(x.api_key),Q(!0)}catch{at("复制失败:请手动选中上方 key 文本复制")}},Ot=()=>{x&&(i.saveKeyInput(x.api_key),G(null),B("已存为当前浏览器 key(原有 key 未被撤销,需要时可单独撤销)。"))},te=async nt=>{const Xt=(()=>{try{return _l().slice(-4)}catch{return""}})(),ee=nt.id==="legacy"?"(主 key:撤销后当前浏览器保存的 key 也可能随之失效,需重新登录拿新 key)":nt.hint&&nt.hint===Xt?"(这就是本浏览器当前在用的 key,撤销后本页会立刻未连接)":"";if(window.confirm(`撤销 key「${nt.label}」(后 4 位 ${nt.hint||"无"})吗?${ee}撤销不可恢复。`)){B(""),at("");try{await tt($.userKey(nt.id),"DELETE"),B(`已撤销 key「${nt.label}」。`),await I()}catch(ct){at(ct instanceof Error?ct.message:"撤销失败")}}};return s.jsxs(Ve,{id:"nav-key",title:"API Key",children:[s.jsxs(Dt,{children:[s.jsx("input",{type:"password",placeholder:"粘贴你的 X-API-Key(与调 API 用的同一个)",autoComplete:"off",value:r,onChange:nt=>m(nt.target.value)}),s.jsx("button",{className:"primary",onClick:()=>{i.saveKeyInput(r),m("")},children:"保存到本浏览器"}),s.jsx("button",{onClick:i.clearKeyInput,children:"清除"}),s.jsx("span",{className:"muted",children:i.keyState})]}),s.jsx("div",{children:s.jsx("span",{className:"muted",children:i.quotaText})}),!i.keySaved&&s.jsx("div",{children:s.jsx("span",{className:"muted",children:"先粘贴并保存已有 key,再生成或管理 key(生成接口本身也要用已有 key 鉴权)。"})}),i.keySaved&&s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("input",{placeholder:"新 key 备注(可选,默认 api-key,如 harness2-temp)",autoComplete:"off",value:o,onChange:nt=>_(nt.target.value)}),s.jsx("button",{className:"primary",onClick:()=>void V(),children:"生成新 key"}),s.jsx("button",{onClick:()=>void I(),children:"刷新列表"})]}),x&&s.jsxs("div",{children:[s.jsx("div",{children:s.jsxs("span",{className:"muted",children:["新 key(",x.label,",后 4 位 ",x.hint,"):只显示一次,关闭后无法再查看。"]})}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",readOnly:!0,value:x.api_key,onFocus:nt=>nt.target.select()}),s.jsx("button",{className:"primary",onClick:()=>void dt(),children:U?"已复制":"复制"}),s.jsx("button",{onClick:Ot,children:"存为当前浏览器 key"}),s.jsx("button",{onClick:()=>G(null),children:"关闭(不再显示)"})]})]}),b&&s.jsx("div",{children:s.jsx("span",{className:"muted",children:b})}),lt&&s.jsx("div",{children:s.jsx("span",{children:lt})}),s.jsxs("div",{children:[C.length===0&&s.jsx("span",{className:"muted",children:"暂无 key(或列表加载失败,见上方报错)。"}),C.map(nt=>s.jsxs("div",{children:[s.jsx("span",{children:nt.label})," ",s.jsxs("span",{className:"muted",children:["后 4 位 ",nt.hint||"无"," · 创建 ",Xa(nt.created_at)," · 最近使用 ",nt.last_used_at?Xa(nt.last_used_at):"未使用过"]})," ",nt.revoked_at?s.jsxs("span",{className:"muted",children:["已撤销(",Xa(nt.revoked_at),")"]}):s.jsx("button",{onClick:()=>void te(nt),children:"撤销"})]},nt.id))]})]})]})}function jg(){const i=Mt();return s.jsxs(Ve,{id:"adminCard",title:s.jsxs(s.Fragment,{children:["管理区 ",s.jsx("span",{className:"muted",children:"(仅全局管理员)"})]}),children:[s.jsx("div",{className:"muted",children:i.adminGate}),i.adminBody?s.jsxs(s.Fragment,{children:[s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"要查配额的用户 id",value:i.adminUserId,onChange:r=>i.setAdminUserId(r.target.value)}),s.jsx("button",{onClick:i.adminQuota,children:"查该用户配额"})]}),s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.adminSweep,children:"手动触发 sweep(清理陈旧 running 任务)"}),s.jsx("button",{onClick:i.adminBackup,children:"手动触发备份"})]}),s.jsx("div",{className:"muted",children:i.adminResult})]}):null]})}function Tg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState("");return s.jsxs(Ve,{id:"nav-projects",title:"项目",children:[s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"项目",value:i.projectId,onChange:x=>i.selectProject(x.target.value),children:[i.projects.length===0?s.jsx("option",{value:"",children:"(先加载项目)"}):null,i.projects.map(x=>s.jsxs("option",{value:x.id,children:[x.name," (",Me(x.id),")"]},x.id))]}),s.jsx("button",{onClick:i.refreshProjects,children:"刷新"})]}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"新项目名",value:r,onChange:x=>m(x.target.value)}),s.jsxs("select",{"aria-label":"从 GitHub 仓库选",value:o,onChange:x=>{_(x.target.value),x.target.value&&N(x.target.value)},children:[s.jsx("option",{value:"",children:"(从 GitHub App 安装仓库里选,或手动输入)"}),i.githubRepos.map(x=>s.jsx("option",{value:x.clone_url,children:x.repo_full_name},x.clone_url))]}),s.jsx("input",{type:"text",placeholder:"repo_url(可选)",value:C,onChange:x=>N(x.target.value)}),s.jsx("button",{onClick:async()=>{await i.createProject(r,C),m(""),N(""),_("")},children:"新建项目"})]}),s.jsx("span",{className:"muted",children:i.projectMsg})]})}function _g(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState("contributor"),C=i.projects.find(N=>N.id===i.projectId);return s.jsxs(Ve,{title:"项目成员",children:[C?s.jsxs("div",{className:"muted",children:[C.name," | ",C.id," | 仓库 ",C.repo_url||"未绑定"," | 我的角色 ",C.my_role||"未知"]}):s.jsx("div",{className:"muted",children:"先选项目"}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"成员 user_id 或用户名",value:r,onChange:N=>m(N.target.value)}),s.jsxs("select",{"aria-label":"邀请角色",value:o,onChange:N=>_(N.target.value),children:[s.jsx("option",{value:"viewer",children:"viewer(只读)"}),s.jsx("option",{value:"contributor",children:"contributor(可建任务)"}),s.jsx("option",{value:"maintainer",children:"maintainer(可批合并)"}),s.jsx("option",{value:"owner",children:"owner(可管项目)"})]}),s.jsx("button",{onClick:async()=>{await i.inviteMember(r,o),m("")},children:"邀请成员"}),s.jsx("button",{onClick:i.refreshMembers,children:"刷新成员"})]}),i.memberError?s.jsx("div",{className:"muted",children:i.memberError}):i.members.length===0?s.jsx("div",{className:"muted",children:"先选项目"}):s.jsx(ru,{children:i.members.map(N=>{const x=(N.username||"")+(N.username?"("+String(N.user_id).slice(0,8)+")":String(N.user_id).slice(0,8));return s.jsxs("li",{children:[s.jsx("span",{className:"row-main",children:x}),s.jsx("select",{"aria-label":"成员角色",value:N.role||"viewer",onChange:G=>void i.changeMemberRole(N.user_id,G.target.value),children:Ly.map(G=>s.jsx("option",{value:G,children:G},G))})]},N.user_id)})}),s.jsx("span",{className:"muted",children:i.memberMsg})]})}function Eg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState("");return s.jsxs(Ve,{id:"nav-env",title:s.jsxs(s.Fragment,{children:["环境 ",s.jsx("span",{className:"muted",children:"(选、建、管:当前项目的基准检出)"})]}),children:[s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.refreshEnvs,children:"刷新"}),s.jsx("span",{className:"muted",children:i.envCount})]}),i.envs.length===0?s.jsx("div",{className:"muted",children:"先选项目"}):s.jsx(ru,{children:i.envs.map(x=>s.jsxs("li",{children:[s.jsxs("span",{className:"row-main",children:[x.name,"(",Me(x.id),") / 分支 ",x.branch||"默认分支"," / 执行器 ",x.executor||"不限"," / 状态 ",x.status,x.status==="failed"&&x.error_text?" / 失败原因:"+x.error_text:""]}),x.status==="archived"?null:s.jsx("button",{onClick:()=>void i.archiveEnv(x.id),children:"归档"})]},x.id))}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"新环境名",value:r,onChange:x=>m(x.target.value)}),s.jsx("input",{type:"text",placeholder:"分支(可选,空=默认分支)",value:o,onChange:x=>_(x.target.value)}),s.jsxs("select",{"aria-label":"新环境执行器",value:C,onChange:x=>N(x.target.value),children:[s.jsx("option",{value:"",children:"执行器:不限"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"docker",children:"docker"})]}),s.jsx("button",{onClick:async()=>{await i.createEnv(r,o,C),m(""),_("")},children:"新建环境"})]}),s.jsx("span",{className:"muted",children:i.envMsg})]})}function Ng(){const i=Mt(),[r,m]=v.useState("");return s.jsxs(Ve,{title:"仓库与环境上下文",children:[s.jsx("div",{className:"muted",children:i.envRepoLine||"先选项目"}),s.jsx("div",{className:"muted",children:i.envCount}),i.envRepoBar?s.jsxs(Dt,{children:[s.jsxs("select",{"aria-label":"补仓库",value:r,onChange:o=>m(o.target.value),children:[s.jsx("option",{value:"",children:"(从 GitHub App 安装仓库里选)"}),i.githubRepos.map(o=>s.jsx("option",{value:o.clone_url,children:o.repo_full_name},o.clone_url))]}),s.jsx("button",{onClick:()=>void i.saveEnvRepo(r),children:"保存仓库"})]}):null,s.jsx("span",{className:"muted",children:i.envRepoMsg})]})}function Cg(){const i=Mt();return s.jsxs(Ve,{id:"nav-workers",title:"Workers",children:[s.jsx(Dt,{children:s.jsx("button",{onClick:i.refreshWorkers,children:"刷新"})}),i.workersError?s.jsx("div",{className:"muted",children:i.workersError}):i.workers===null?s.jsx("div",{className:"muted",children:i.workersSummary||"未加载"}):i.workers.length===0?s.jsx("div",{className:"muted",children:"无 worker 注册"}):s.jsx(ru,{children:i.workers.map((r,m)=>{const o=r.running===void 0||r.running===null?"?":r.running,_=r.capacity===void 0||r.capacity===null?"?":r.capacity,C=Qh(r),N=r.alive!==void 0&&r.alive!==null?!!r.alive:C.age!==null&&C.age<=120,x=N?" / 在线":" / 离线(占用为上次上报值)";return s.jsx("li",{className:N?"is-online":"is-offline",children:s.jsxs("span",{className:"row-main",children:[r.worker_id||r.id||"?"," / ",r.executor||""," / 占用 ",o,"/",_,x," / 最后心跳 ",C.text]})},m)})})]})}function Ag(){const i=Mt();return s.jsxs(Ve,{title:"健康与配额",children:[s.jsxs(Dt,{children:[s.jsx("span",{className:"muted",children:i.healthText}),s.jsx("button",{onClick:i.refreshHealth,children:"刷新"})]}),s.jsx("div",{children:s.jsx("span",{className:"muted",children:i.quotaText})}),s.jsx("div",{className:"muted",children:i.workersSummary})]})}function Mg(){const i=Mt();return s.jsxs(Ve,{id:"nav-skills",title:"技能与 MCP",children:[s.jsx("div",{className:"muted",children:"反映宿主租户 home,容器内 home 可能不同;重载只在 schema 枚举里,当前 pin 的二进制拒绝时原样 502;OAuth 只发起登录,不代表登录完成。"}),s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.refreshSkills,children:"刷新"}),s.jsx("span",{className:"muted",children:i.skillMsg})]}),s.jsx("h3",{children:"技能"}),i.skillError?s.jsx("div",{className:"muted",children:i.skillError}):s.jsx(Dl,{empty:"暂无技能",items:i.skills.map((r,m)=>s.jsxs("span",{className:"row-main",children:[r.name||r.id||"",r.description?" - "+r.description:"",r.detail?" - "+r.detail:""]},m))}),s.jsx("h3",{children:"应用"}),s.jsx(Dl,{empty:"暂无应用",items:i.apps.map((r,m)=>s.jsxs("span",{className:"row-main",children:[r.name||r.id||"",r.description?" - "+r.description:""]},m))}),s.jsx("h3",{children:"MCP 服务"}),s.jsx(Dl,{empty:"暂无 MCP 服务",items:i.mcpServers.map((r,m)=>{const o=r.detail||r.details||r.state||"";return s.jsxs("span",{className:"row-main",children:[r.name||r.id||""," | 状态 ",r.status||"",o?" | "+o:""]},m)})})]})}function Og(){const i=Mt(),[r,m]=v.useState("");return s.jsxs(Ve,{title:"MCP 操作",children:[s.jsxs(Dt,{children:[s.jsx("button",{onClick:i.reloadMcp,children:"重载配置"}),s.jsx("span",{className:"muted",children:i.mcpMsg})]}),s.jsxs(Dt,{children:[s.jsx("input",{type:"text",placeholder:"MCP 服务名",value:r,onChange:o=>m(o.target.value)}),s.jsx("button",{onClick:()=>void i.mcpOauth(r),children:"发起 OAuth 登录"}),s.jsx("span",{className:"muted",children:i.mcpOauthMsg})]}),i.mcpOauthBox?s.jsx("pre",{children:i.mcpOauthBox}):null]})}function zg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState(""),[x,G]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("input",{placeholder:"自动化名称(同项目内启用中的名称唯一)",style:{width:"100%"},value:r,onChange:U=>m(U.target.value)}),s.jsx("textarea",{placeholder:"定时任务内容(创建只登记定义与到期状态;执行由后续执行器经 claim 抢单后建任务,不另起调度器)",value:o,onChange:U=>_(U.target.value)}),s.jsxs(Dt,{children:[s.jsx("input",{placeholder:"间隔秒数(默认 86400,最小 60)",style:{width:"40%"},value:C,onChange:U=>N(U.target.value)}),s.jsx("input",{placeholder:"仓库(可选)",style:{width:"40%"},value:x,onChange:U=>G(U.target.value)}),s.jsx("button",{className:"primary",onClick:async()=>{await i.createAutomation(r,o,C,x),m(""),_(""),N(""),G("")},children:"创建自动化"}),s.jsx("button",{onClick:i.refreshAutomations,children:"刷新自动化"}),s.jsx("span",{className:"muted",children:i.autoMsg})]}),s.jsx(Dl,{empty:"(暂无自动化)",items:i.automations.map(U=>s.jsxs("span",{className:"row-main",children:["[",U.status,U.due?"|到期":"","] ",U.name,"|每 ",U.interval_seconds," 秒|下次 ",Xa(U.next_run_at),U.status==="active"?s.jsxs(s.Fragment,{children:[" ",s.jsx("button",{onClick:()=>i.cancelAutomation(U.id),children:"取消"})]}):null]},U.id))})]})}function Rg(){var m,o,_,C;const i=Mt(),r=i.triage;return i.triageError?s.jsx("div",{className:"muted",children:i.triageError}):r?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["到期自动化(",((m=r.counts)==null?void 0:m.automations_due)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.automations_due||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[N.name,"|每 ",N.interval_seconds," 秒"]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["失败/中断任务(",((o=r.counts)==null?void 0:o.failed_tasks)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.failed_tasks||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[Me(N.id),"|",N.status,"|",String(N.prompt||"").slice(0,80)]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["待处理后续消息(",((_=r.counts)==null?void 0:_.pending_followups)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.pending_followups||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:["任务 ",Me(N.task_id),"|",String(N.body||"").slice(0,80)]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["最近自动化产出(",((C=r.counts)==null?void 0:C.recent_runs)||0,")"]}),s.jsx(Dl,{empty:"(无)",items:(r.recent_runs||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[Me(N.automation_id),"|",N.status,N.task_id?"|任务 "+Me(N.task_id):"",N.task_status?"|"+N.task_status:""]},x))})]})]}):s.jsx("div",{className:"muted",children:"(先选项目)"})}function Dg(){return s.jsx(Ve,{id:"nav-automations",title:"自动化",children:s.jsx(zg,{})})}function Ug(){const i=Mt();return s.jsxs(Ve,{id:"nav-triage",title:"分诊收件箱",children:[s.jsx(Dt,{children:s.jsx("button",{onClick:i.refreshTriage,children:"刷新分诊"})}),s.jsx(Rg,{})]})}const Hg=[["#sec-dispatch","派发"],["#sec-tasks","任务"],["#sec-conv","对话"],["#sec-projects","项目"],["#sec-env","环境"],["#sec-workers","Workers"],["#sec-skills","技能"],["#sec-automations","自动化"],["#sec-triage","分诊"],["#sec-admin","管理区"],["#sec-key","API Key"]];function Bg(){return s.jsxs("header",{className:"dash-topbar",children:[s.jsxs("div",{className:"dash-topbar-row",children:[s.jsx("span",{className:"dash-brand",children:"Codex 命令台"}),s.jsx(qg,{}),s.jsx("span",{className:"muted dash-hide-sm",children:s.jsx(Yg,{})}),s.jsx("span",{className:"muted dash-hide-sm",children:s.jsx(wg,{})}),s.jsx("span",{className:"muted dash-stamp",children:s.jsx(Gg,{})})]}),s.jsx("nav",{className:"dash-nav","aria-label":"页面导航",children:Hg.map(([i,r])=>s.jsx("a",{href:i,children:r},i))})]})}function qg(){const i=Mt();return s.jsx("span",{className:i.keySaved?"dash-status ok":"dash-status off",children:i.keySaved?"● 已连接":"○ 未连接"})}function Yg(){return s.jsx(s.Fragment,{children:Mt().healthText})}function wg(){return s.jsx(s.Fragment,{children:Mt().quotaText})}function Gg(){return s.jsxs(s.Fragment,{children:["自动刷新 · 每 10 秒 · 已刷新 ",Mt().refreshStamp]})}function Qg(){const i=ag();tg(m=>i.refreshAll(m),1e4),eg(()=>i.refreshSlow(),6e4);const r=()=>{var m;(m=document.getElementById("sec-dispatch"))==null||m.scrollIntoView({behavior:"smooth"})};return s.jsxs(Gh.Provider,{value:i,children:[s.jsx(Bg,{}),s.jsxs("main",{className:"dash-page",children:[s.jsx(ng,{}),s.jsxs("div",{className:"dash-col dash-col-left",children:[s.jsxs("section",{id:"sec-tasks",className:"dash-section card",children:[s.jsx("h2",{children:"任务列表"}),s.jsx(ig,{onNew:r})]}),s.jsxs("section",{id:"sec-projects",className:"dash-section",children:[s.jsx(Tg,{}),s.jsx(_g,{})]})]}),s.jsxs("div",{className:"dash-col dash-col-mid",children:[s.jsx("section",{id:"sec-dispatch",className:"dash-section",children:s.jsx(ug,{})}),s.jsxs("section",{id:"sec-conv",className:"dash-section",children:[s.jsxs("div",{className:"card",children:[s.jsx("h2",{children:"对话"}),s.jsx(dg,{})]}),s.jsx(bg,{})]})]}),s.jsxs("div",{className:"dash-col dash-col-right",children:[s.jsxs("section",{id:"sec-env",className:"dash-section",children:[s.jsx(Eg,{}),s.jsx(Ng,{})]}),s.jsxs("section",{id:"sec-workers",className:"dash-section",children:[s.jsx(Cg,{}),s.jsx(Ag,{})]}),s.jsxs("section",{id:"sec-skills",className:"dash-section",children:[s.jsx(Mg,{}),s.jsx(Og,{})]}),s.jsx("section",{id:"sec-automations",className:"dash-section",children:s.jsx(Dg,{})}),s.jsx("section",{id:"sec-triage",className:"dash-section",children:s.jsx(Ug,{})}),s.jsx("section",{id:"sec-admin",className:"dash-section",children:s.jsx(jg,{})}),s.jsx("section",{id:"sec-key",className:"dash-section",children:s.jsx(xg,{})})]})]})]})}ky.createRoot(document.getElementById("root")).render(s.jsx(Uy.StrictMode,{children:s.jsx(Qg,{})})); diff --git a/cloud/server.py b/cloud/server.py index 4490edf..3e48b25 100644 --- a/cloud/server.py +++ b/cloud/server.py @@ -4480,9 +4480,12 @@ class CloudControlPlaneHandler(BaseHTTPRequestHandler): conn = self._db() try: atts = _attachments_map(conn, [task_id])[task_id] + # 详情与列表口径一致:单任务也一次聚合回 total_tokens, + # 否则详情里的 token 栏只能显示占位。 + tok = _task_tokens_map(conn, [task_id]).get(task_id, 0) finally: conn.close() - task = _task_to_dict(row, atts) + task = _task_to_dict(row, atts, tok) with _auth_store(self.server.db_path) as store: if not store.check_permission(user_id, task["project_id"], "read"): self._send_json(403, {"error": "forbidden"}) diff --git a/cloud/tests/test_task_list_tokens.py b/cloud/tests/test_task_list_tokens.py index 386ab33..f0bfca6 100644 --- a/cloud/tests/test_task_list_tokens.py +++ b/cloud/tests/test_task_list_tokens.py @@ -97,6 +97,24 @@ class ListTokensTestCase(unittest.TestCase): self.assertEqual(by_id[t1["id"]]["total_tokens"], 170) self.assertEqual(by_id[t2["id"]]["total_tokens"], 0) + def test_single_task_returns_aggregated_total_tokens(self): + # 详情接口(_get_task)与列表口径一致:单任务也聚合回 + # total_tokens,否则详情里的 token 栏只能显示占位。 + pid = self.project["id"] + _, t1 = self._req("POST", "/tasks", + {"project_id": pid, "prompt": "详情成本"}, + self.owner_key) + store = CostStore(self.db_path) + try: + store.record(t1["id"], pid, "m", input_tokens=60, + output_tokens=40, source="actual") + finally: + store._conn.close() + status, body = self._req( + "GET", "/tasks/%s" % t1["id"], key=self.owner_key) + self.assertEqual(status, 200, body) + self.assertEqual(body["total_tokens"], 100) + def test_tokens_map_missing_table_is_zero_not_error(self): import sqlite3 conn = sqlite3.connect(":memory:") From 994c4ea5d10fb6f1e70a2ecd34ad497164a2e42e Mon Sep 17 00:00:00 2001 From: host Date: Fri, 30 Oct 2026 00:38:33 +0800 Subject: [PATCH 2/2] =?UTF-8?q?console:=20=E4=BB=BB=E5=8A=A1=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E8=87=AA=E5=8A=A8=E6=98=BE=E7=A4=BA=E6=88=90=E6=9C=AC?= =?UTF-8?q?=E6=98=8E=E7=BB=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 打开详情就自动拉 GET /tasks/{id}/cost(不再只靠 “查成本”按钮出 JSON),详情顶部新一行:美元、总 token(实际/估算、缓存、无价单列)、轮数、fallback 次数;美元小于 1 美分时用 4 位小数,避免小任务 显示成 $0.00 误导成免费;加载中/失败有各自的 弱化文案,成本拉失败不影响详情其它内容;原 “查成本”按钮不动,仍可手动拉原始 JSON。 服务端不用改:成本接口与 _get_task 的 token 聚合 都已在 #150 / 详情 meta 那单里就位。 --- cloud/console-react/src/api/taskMeta.ts | 9 ++++ cloud/console-react/src/api/types.ts | 1 + cloud/console-react/src/context.ts | 4 +- .../src/hooks/useConsoleStore.ts | 2 +- .../console-react/src/hooks/useTaskDetail.ts | 21 +++++++-- .../src/sections/TaskDetailPanel.tsx | 5 +- cloud/console.html | 46 +++++++++---------- 7 files changed, 57 insertions(+), 31 deletions(-) diff --git a/cloud/console-react/src/api/taskMeta.ts b/cloud/console-react/src/api/taskMeta.ts index a164b35..93c483f 100644 --- a/cloud/console-react/src/api/taskMeta.ts +++ b/cloud/console-react/src/api/taskMeta.ts @@ -70,6 +70,15 @@ export function durationOf(t: Task): [string, string] { return ["—", "总耗时:无可用时间戳"]; } +// 成本美元:usd_micros 是微美元(1 美元 = 1,000,000)。 +// 小于 1 美分时用 4 位小数,否则 2 位——小任务直接 toFixed(2) +// 会把 $0.003 显示成 $0.00,误导成免费。 +export function fmtCostUsd(micros: number | null | undefined): string { + if (micros === null || micros === undefined || !Number.isFinite(Number(micros))) return "—"; + const v = Number(micros) / 1000000; + return "$" + (v > 0 && v < 0.01 ? v.toFixed(4) : v.toFixed(2)); +} + export function tokenOf(t: Task): [string, string] { const total = num(t.total_tokens); if (total !== null) { diff --git a/cloud/console-react/src/api/types.ts b/cloud/console-react/src/api/types.ts index 9ccccbd..eb6ae22 100644 --- a/cloud/console-react/src/api/types.ts +++ b/cloud/console-react/src/api/types.ts @@ -24,6 +24,7 @@ export interface Task { child_model?: string; child_effort?: string; approval?: string; result_text?: string; error_text?: string; } +export interface TaskCost { task_id?: string; project_id?: string; total_tokens?: number; usd_micros?: number; turns?: number; fallback_count?: number; actual_tokens?: number; estimated_tokens?: number; cached_input_tokens?: number; unpriced_actual_tokens?: number } export interface Review { id: string; target_type?: string; branch?: string; sha?: string; instructions?: string; status?: string; created_at?: number; findings?: string } export interface Approval { id: string; kind?: string; status?: string; summary?: string; decision?: string; decided_by?: string; decided_at?: number } export interface Followup { mode?: string; status?: string; sender_task_id?: string; body?: string } diff --git a/cloud/console-react/src/context.ts b/cloud/console-react/src/context.ts index 6ab0d69..917bc20 100644 --- a/cloud/console-react/src/context.ts +++ b/cloud/console-react/src/context.ts @@ -1,5 +1,5 @@ import { createContext, useContext } from "react"; -import type { Automation, Env, Member, Project, Review, Approval, Followup, PeerMessage, Task, ThreadInfo, Triage, Worker, SkillItem, McpServer, Agent, DispatchBody, ReviewBody, TraceEntry, ChatHistory } from "./api/types"; +import type { Automation, Env, Member, Project, Review, Approval, Followup, PeerMessage, Task, TaskCost, ThreadInfo, Triage, Worker, SkillItem, McpServer, Agent, DispatchBody, ReviewBody, TraceEntry, ChatHistory } from "./api/types"; export interface ConsoleCtx { keySaved: boolean; keyState: string; @@ -23,7 +23,7 @@ export interface ConsoleCtx { statusFilter: string; setStatusFilter: (v: string) => void; executorFilter: string; setExecutorFilter: (v: string) => void; searchText: string; setSearchText: (v: string) => void; filteredTasks: Task[]; currentTask: Task | null; detailBody: string; actionMsg: string; actionReasons: string; - showDetail: (id: string) => void; doAction: (kind: string) => void; taskCost: () => void; costBox: string; + showDetail: (id: string) => void; doAction: (kind: string) => void; taskCost: () => void; costBox: string; costSummary: TaskCost | null | undefined; forkVisible: boolean; setForkVisible: (v: boolean) => void; forkTask: (msg: string) => Promise; forkMsg: string; // Continue input is ContinuePanel (ChatInput); its send path is sendChatMessage below. coordChildren: Task[]; coordText: string; agents: Agent[]; agentsNote: string; diff --git a/cloud/console-react/src/hooks/useConsoleStore.ts b/cloud/console-react/src/hooks/useConsoleStore.ts index ba69862..1cdcee5 100644 --- a/cloud/console-react/src/hooks/useConsoleStore.ts +++ b/cloud/console-react/src/hooks/useConsoleStore.ts @@ -130,7 +130,7 @@ export function useConsoleStore(): ConsoleCtx { filteredTasks: taskList.filteredTasks, currentTask: detail.currentTask, detailBody: detail.detailBody, actionMsg: detail.actionMsg, actionReasons: detail.actionReasons, showDetail: (id: string) => void detail.showDetail(id), - doAction: detail.doAction, taskCost: detail.taskCost, costBox: detail.costBox, + doAction: detail.doAction, taskCost: detail.taskCost, costBox: detail.costBox, costSummary: detail.costSummary, forkVisible: detail.forkVisible, setForkVisible: detail.setForkVisible, forkTask: detail.forkTask, forkMsg: detail.forkMsg, coordChildren: detail.coordChildren, coordText: "", agents: detail.agents, agentsNote: detail.agentsNote, reviews: detail.reviews, reviewMsg: detail.reviewMsg, reviewError: detail.reviewError, diff --git a/cloud/console-react/src/hooks/useTaskDetail.ts b/cloud/console-react/src/hooks/useTaskDetail.ts index b6a0894..b3ea4df 100644 --- a/cloud/console-react/src/hooks/useTaskDetail.ts +++ b/cloud/console-react/src/hooks/useTaskDetail.ts @@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { api, getKey } from "../api/client"; import { paths } from "../api/paths"; import { TRACE_TERMINAL } from "../api/types"; -import type { Agent, Approval, ChatHistory, Followup, PeerMessage, Review, Task, ThreadInfo, TraceEntry } from "../api/types"; +import type { Agent, Approval, ChatHistory, Followup, PeerMessage, Review, Task, TaskCost, ThreadInfo, TraceEntry } from "../api/types"; // Task detail state: the selected task, its trace SSE/one-shot stream, // and every structured sub-list. Chat sending lives here too: @@ -13,6 +13,9 @@ export function useTaskDetail(getRole: (pid?: string) => string | null, onTasksR const [actionMsg, setActionMsg] = useState(""); const [actionReasons, setActionReasons] = useState(""); const [costBox, setCostBox] = useState(""); + // 成本明细:打开详情就自动加载(不再只靠“查成本”按钮出 JSON)。 + // undefined = 加载中,null = 加载失败,对象 = 已加载。 + const [costSummary, setCostSummary] = useState(undefined); const [forkVisible, setForkVisible] = useState(false); const [forkMsg, setForkMsg] = useState(""); const [coordChildren, setCoordChildren] = useState([]); @@ -68,6 +71,13 @@ export function useTaskDetail(getRole: (pid?: string) => string | null, onTasksR } catch { setCoordChildren([]); } }, []); + const loadCost = useCallback(async (taskId: string) => { + try { + const c = await api(paths.taskCost(taskId)); + setCostSummary(c); + } catch { setCostSummary(null); } + }, []); + const loadFollowups = useCallback(async (taskId: string) => { try { const d = await api<{ followups: Followup[] }>(paths.taskFollowups(taskId)); setFollowups(d.followups || []); } catch { setFollowups([]); } @@ -215,6 +225,8 @@ export function useTaskDetail(getRole: (pid?: string) => string | null, onTasksR if (!body) body = "(暂无 result/error 输出)"; setDetailBody(body); setCostBox(""); + setCostSummary(undefined); + void loadCost(taskId); setForkVisible(false); setForkMsg(""); setPeerMsg(""); @@ -247,7 +259,7 @@ export function useTaskDetail(getRole: (pid?: string) => string | null, onTasksR setCurrentTask(null); setDetailBody("加载失败:" + e.message); } - }, [stopTrace, startTrace, loadAgents, loadCoordChildren, loadChatHistory, loadFollowups, loadPeerMessages, loadThread, loadThreads, loadReviews, loadApprovals, getRole]); + }, [stopTrace, startTrace, loadAgents, loadCoordChildren, loadChatHistory, loadFollowups, loadPeerMessages, loadThread, loadThreads, loadReviews, loadApprovals, loadCost, getRole]); const refreshDetailLists = useCallback(async () => { const t = currentTaskRef.current; @@ -269,7 +281,8 @@ export function useTaskDetail(getRole: (pid?: string) => string | null, onTasksR void loadPeerMessages(t.id); void loadThread(t.id); void loadThreads(t.id); - }, [loadFollowups, loadChatHistory, loadReviews, loadApprovals, loadCoordChildren, loadAgents, loadPeerMessages, loadThread, loadThreads]); + void loadCost(t.id); + }, [loadFollowups, loadChatHistory, loadReviews, loadApprovals, loadCoordChildren, loadAgents, loadPeerMessages, loadThread, loadThreads, loadCost]); const doAction = useCallback(async (kind: string) => { const t = currentTaskRef.current; @@ -409,7 +422,7 @@ export function useTaskDetail(getRole: (pid?: string) => string | null, onTasksR useEffect(() => () => stopTrace(), [stopTrace]); return { - currentTask, detailBody, actionMsg, actionReasons, costBox, forkVisible, setForkVisible, forkMsg, + currentTask, detailBody, actionMsg, actionReasons, costBox, costSummary, forkVisible, setForkVisible, forkMsg, coordChildren, agents, agentsNote, reviews, reviewMsg, reviewError, traceEntries, traceNote, traceDone, traceKind, setTraceKind, traceMsg, followups, approvals, approvalMsg, peerMessages, peerMsg, threadText, threadGateNote, threadMsg, threadList, chatMsg, chatHistory, diff --git a/cloud/console-react/src/sections/TaskDetailPanel.tsx b/cloud/console-react/src/sections/TaskDetailPanel.tsx index 5e6c07b..b42731e 100644 --- a/cloud/console-react/src/sections/TaskDetailPanel.tsx +++ b/cloud/console-react/src/sections/TaskDetailPanel.tsx @@ -2,7 +2,7 @@ import { useConsole } from "../context"; import { Card } from "../components/ui"; import { shortId, fmt } from "../api/client"; import { STATUS_EXPLAIN } from "../api/types"; -import { firstChar, durationOf, tokenOf } from "../api/taskMeta"; +import { firstChar, durationOf, tokenOf, fmtCostUsd } from "../api/taskMeta"; import DetailActions from "./detail/DetailActions"; import ReviewPanel from "./detail/ReviewPanel"; import { CoordPanel, AgentsPanel, ApprovalPanel, PeerPanel, ThreadPanel } from "./detail/DetailLists"; @@ -22,6 +22,9 @@ export default function TaskDetailPanel() {
状态 {t.status}({STATUS_EXPLAIN[t.status] || "未知状态"})
耗时 {dur} · {tok} +
{ctx.costSummary === undefined ? 成本加载中… + : ctx.costSummary === null ? 成本明细加载失败(“查成本”按钮仍可手动拉取原始 JSON) + : 成本 {fmtCostUsd(ctx.costSummary.usd_micros)} | token {(ctx.costSummary.total_tokens ?? 0).toLocaleString()}(实际 {(ctx.costSummary.actual_tokens ?? 0).toLocaleString()} / 估算 {(ctx.costSummary.estimated_tokens ?? 0).toLocaleString()},缓存 {(ctx.costSummary.cached_input_tokens ?? 0).toLocaleString()},无价 {(ctx.costSummary.unpriced_actual_tokens ?? 0).toLocaleString()})| 轮数 {ctx.costSummary.turns ?? 0} | fallback {ctx.costSummary.fallback_count ?? 0}}
任务 {t.id} | turn {shortId(t.turn_id)} | root turn {shortId(t.root_turn_id)}
executor {t.executor || ""} | 主机 {t.worktree_host || ""}
模型 {t.model || "默认"} | 强度 {t.effort || "默认"} diff --git a/cloud/console.html b/cloud/console.html index ca75ff5..661d321 100644 --- a/cloud/console.html +++ b/cloud/console.html @@ -4,7 +4,7 @@ Codex 命令台 - +`),C(X||"(暂无 result/error 输出)")}catch{}Zt(H.id),Pe(H.id),qe(H.id),Tl(H.id),da(H),sl(H.id),fl(H.id),Gt(H.id),Ul(H.id),Dl(H.id)}},[Zt,Pe,qe,Tl,da,sl,fl,Gt,Ul,Dl]),ma=v.useCallback(async H=>{const D=ne.current;if(!D)return;const X={cancel:"确定取消该任务吗?",merge:"确定把 completed 任务标为 merged 吗?",pr:"确定为该任务提 PR 吗?(会在仓库真实建 PR)"};if(!(X[H]&&!window.confirm(X[H])))try{const K=await P($.taskAction(D.id,H),"POST",{});x(H+" 已提交:"+JSON.stringify(K).slice(0,300)),r(),await ge(D.id)}catch(K){x(H+" 失败:"+K.message)}},[ge,r]),su=v.useCallback(async()=>{const H=ne.current;if(H)try{const D=await P($.taskCost(H.id));b(JSON.stringify(D,null,2).slice(0,4e3))}catch(D){b("查成本失败:"+D.message)}},[]),fu=v.useCallback(async H=>{const D=ne.current;if(D){if(!H.trim()){dt("分支消息必填");return}if(!uu.includes(D.status)){dt("仅终态任务可分支");return}try{const X=await P($.taskFork(D.id),"POST",{message:H.trim()});dt("分支任务已建:"+X.id.slice(0,8)),r()}catch(X){dt("分支失败:"+X.message)}}},[r]),Fl=v.useCallback(async H=>{const D=ne.current;if(D)try{await P($.taskReviews(D.id),"POST",H),Vt("评审已登记(requested)"),await qe(D.id)}catch(X){Vt("登记评审需求失败:"+X.message)}},[qe]),Ee=v.useCallback(H=>{const D=ne.current;if(!D)return;const X=window.prompt("输入该条评审的 findings(将写回记录并标为 completed):");X!==null&&P($.taskReviewFindings(D.id,H),"POST",{findings:X}).then(()=>void qe(D.id)).catch(K=>Vt("写 findings 失败:"+K.message))},[qe]),rl=v.useCallback((H,D)=>{const X=ne.current;if(!X)return;const K=D==="approved"?"approve":"deny";P($.taskApprovalDecision(X.id,H,K),"POST",{}).then(()=>{mt("已记录"+(D==="approved"?"允许":"拒绝")+"(当前版本只留回执,不拦截实时行为)"),Tl(X.id)}).catch(O=>mt("决定失败:"+O.message))},[Tl]),Ne=v.useCallback(async(H,D,X)=>{const K=ne.current;if(K){if(!D.trim()){ae("目标任务 id 不能为空");return}if(!X.trim()){ae("消息正文不能为空");return}try{const O=await P($.taskMessagesTo(D.trim()),"POST",{from_task_id:K.id,body:X.trim(),mode:H});ae("已发送("+O.delivery+")"),await fl(K.id)}catch(O){ae("发送失败:"+O.message)}}},[fl]),ru=v.useCallback((H,D)=>{const X=ne.current;if(!X)return;if(!["completed","failed","interrupted"].includes(X.status)){oe("仅 completed/failed/interrupted 任务可操作线程(merged/merge-failed 不可改,服务端同样 409)");return}const K={};if(H==="rename"){if(!D.trim()){oe("新线程名不能为空");return}K.name=D.trim()}P($.taskThreadAction(X.id,H),"POST",K).then(O=>{oe(H+" 已提交:"+JSON.stringify(O).slice(0,300)),Gt(X.id),Ul(X.id)}).catch(O=>oe(H+" 失败:"+O.message))},[Gt,Ul]),ou=v.useCallback(async H=>{const D=ne.current;if(!D)return;const X=H.trim();if(!X){Ve("消息不能为空");return}try{uu.includes(D.status)&&D.status!=="merged"?(await P($.taskContinue(D.id),"POST",{message:X}),Ve("已重新排队,同一会话继续"),r(),await ge(D.id)):["queued","running"].includes(D.status)?(await P($.taskFollowups(D.id),"POST",{body:X,mode:"direct"}),Ve("已直接发送"),await Zt(D.id),await Pe(D.id)):Ve("merged/merge-failed 任务不可继续,也不可发后续消息")}catch(K){Ve("发送失败:"+K.message)}},[ge,r,Zt,Pe]),du=v.useCallback(async()=>{const H=ne.current;if(!H){_e("先选一个任务");return}try{const D=await P($.taskTrace(H.id)),X=new Blob([JSON.stringify({task_id:H.id,status:D.status,note:D.note||"",count:(D.entries||[]).length,entries:D.entries||[]},null,2)],{type:"application/json"}),K=document.createElement("a");K.href=URL.createObjectURL(X),K.download="trace-"+H.id.slice(0,8)+".json",document.body.appendChild(K),K.click(),K.remove(),setTimeout(()=>URL.revokeObjectURL(K.href),1e3),_e("已下载完整链路 "+(D.entries||[]).length+" 条")}catch(D){_e("下载失败:"+D.message)}},[]);return v.useEffect(()=>()=>ue(),[ue]),{currentTask:m,detailBody:_,actionMsg:N,actionReasons:w,costBox:G,costSummary:B,forkVisible:at,setForkVisible:et,forkMsg:L,coordChildren:zt,agents:nt,agentsNote:te,reviews:yt,reviewMsg:he,reviewError:Ft,traceEntries:Ie,traceNote:Y,traceDone:lt,traceKind:St,setTraceKind:ve,traceMsg:Ue,followups:y,approvals:W,approvalMsg:pt,peerMessages:_t,peerMsg:ut,threadText:ka,threadGateNote:Xe,threadMsg:Rt,threadList:Kl,chatMsg:oa,chatHistory:zl,showDetail:ge,refreshDetailLists:Xa,doAction:ma,taskCost:su,forkTask:fu,postReview:Fl,submitFindings:Ee,decideApproval:rl,postPeer:Ne,threadAction:ru,sendChatMessage:ou,downloadTrace:du,refreshReviews:()=>void qe(),refreshApprovals:()=>void Tl()}}function Py(i){const[r,m]=v.useState([]),[o,_]=v.useState(""),[C,N]=v.useState(null),[x,w]=v.useState(""),U=v.useCallback(async tt=>{const at=tt!==void 0?tt:i();if(!at){m([]);return}try{const et=await P($.projectAutomations(at));m(et.automations||[])}catch(et){_("自动化加载失败:"+et.message)}},[i]),G=v.useCallback(async(tt,at,et,L)=>{const dt=i();if(!dt){_("先选项目");return}if(!tt.trim()){_("自动化名称必填");return}if(!at.trim()){_("定时任务内容必填");return}const zt={name:tt.trim(),prompt:at.trim()};et.trim()&&(zt.interval_seconds=parseInt(et.trim(),10)),L.trim()&&(zt.repo_url=L.trim());try{await P($.projectAutomations(dt),"POST",zt),_("自动化已创建(登记定义,到期后由执行器认领)"),await U(dt)}catch(Jt){_("创建失败:"+Jt.message)}},[i,U]),b=v.useCallback(tt=>{const at=i();at&&P($.projectAutomationCancel(at,tt),"POST",{}).then(()=>{_("自动化已取消"),U(at)}).catch(et=>_("取消失败:"+et.message))},[i,U]),B=v.useCallback(async tt=>{const at=tt!==void 0?tt:i();if(!at){N(null);return}try{const et=await P($.projectTriage(at));N(et),w("")}catch(et){w("分诊加载失败:"+et.message)}},[i]);return{automations:r,autoMsg:o,triage:C,triageError:x,refreshAutomations:U,createAutomation:G,cancelAutomation:b,refreshTriage:B}}function tg(i,r){const m=v.useRef(i);m.current=i,v.useEffect(()=>{const o=setInterval(()=>{const _=document.activeElement;m.current(_?_.tagName==="SELECT":!1)},r);return()=>clearInterval(o)},[r])}function eg(i,r){const m=v.useRef(i);m.current=i,v.useEffect(()=>{const o=setInterval(()=>m.current(),r);return()=>clearInterval(o)},[r])}function lg(i){const r=m=>String(m).padStart(2,"0");return r(i.getHours())+":"+r(i.getMinutes())+":"+r(i.getSeconds())}function ag(){var et;const i=Wy(),r=$y(),m=v.useRef("");m.current=i.projectId;const o=v.useCallback(()=>m.current,[]),_=Py(o),C=v.useCallback(L=>{const dt=i.projects.find(zt=>zt.id===L);return dt&&dt.my_role||null},[i.projects]),N=v.useCallback(()=>{r.refreshTasks(void 0,m.current)},[r]),x=Iy(C,N),[w,U]=v.useState("--:--:--"),G=v.useCallback(L=>{i.setProjectId(L),m.current=L,r.refreshTasks(L),i.refreshEnvs(L),i.refreshMembers(L),i.refreshSkills(L),_.refreshAutomations(L),_.refreshTriage(L)},[i,r,_]),b=(et=i.projects[0])==null?void 0:et.id;v.useEffect(()=>{!i.projectId&&b&&G(b)},[i.projectId,b,G]);const B=v.useCallback(L=>{i.saveKeyInput(L),L.trim()&&(i.refreshHealth(),i.refreshProjects(),i.refreshWorkers(),m.current&&(r.refreshTasks(m.current),i.refreshEnvs(m.current),i.refreshMembers(m.current)),i.loadRelayModels(),i.loadQuota(),i.loadGithubRepos(),i.probeAdmin())},[i,r]),tt=v.useCallback(L=>{if(U(lg(new Date)),!bl()){i.refreshHealth();return}r.refreshTasks(void 0,m.current),i.refreshHealth(),i.loadQuota(),i.refreshWorkers(),i.refreshMembers(),i.refreshSkills(),_.refreshAutomations(),_.refreshTriage(),x.refreshDetailLists(),L||(i.refreshProjects(),i.refreshEnvs())},[i,r,_,x]),at=v.useCallback(()=>{bl()&&(i.loadRelayModels(),i.loadGithubRepos())},[i]);return v.useEffect(()=>{i.refreshHealth(),i.refreshProjects(),i.refreshWorkers(),i.loadQuota(),i.loadGithubRepos(),bl()&&i.loadRelayModels(),i.probeAdmin()},[]),{keySaved:i.keySaved,keyState:i.keyState,saveKeyInput:B,clearKeyInput:i.clearKeyInput,quotaText:i.quotaText,healthText:i.healthText,refreshHealth:i.refreshHealth,adminGate:i.adminGate,adminBody:i.adminBody,adminResult:i.adminResult,adminUserId:i.adminUserId,setAdminUserId:i.setAdminUserId,adminQuota:i.adminQuota,adminSweep:i.adminSweep,adminBackup:i.adminBackup,projects:i.projects,projectId:i.projectId,projectMsg:i.projectMsg,selectProject:G,refreshProjects:i.refreshProjects,createProject:i.createProject,githubRepos:i.githubRepos,workers:i.workers,workersSummary:i.workersSummary,workersError:i.workersError,refreshWorkers:i.refreshWorkers,members:i.members,memberMsg:i.memberMsg,memberError:i.memberError,refreshMembers:()=>void i.refreshMembers(),inviteMember:i.inviteMember,changeMemberRole:i.changeMemberRole,skills:i.skills,apps:i.apps,mcpServers:i.mcpServers,skillMsg:i.skillMsg,skillError:i.skillError,mcpMsg:i.mcpMsg,mcpOauthMsg:i.mcpOauthMsg,mcpOauthBox:i.mcpOauthBox,refreshSkills:()=>void i.refreshSkills(),reloadMcp:i.reloadMcp,mcpOauth:i.mcpOauth,envs:i.envs,envCount:i.envCount,envMsg:i.envMsg,envRepoLine:i.envRepoLine,envRepoBar:i.envRepoBar,envRepoMsg:i.envRepoMsg,envSelect:i.envSelect,setEnvSelect:i.setEnvSelect,refreshEnvs:()=>void i.refreshEnvs(),createEnv:i.createEnv,archiveEnv:i.archiveEnv,saveEnvRepo:i.saveEnvRepo,models:i.models,modelCustomVisible:i.modelCustomVisible,tasks:r.tasks,taskCountText:r.taskCountText,taskError:r.taskError,refreshTasks:()=>void r.refreshTasks(void 0,m.current),statusFilter:r.statusFilter,setStatusFilter:r.setStatusFilter,executorFilter:r.executorFilter,setExecutorFilter:r.setExecutorFilter,searchText:r.searchText,setSearchText:r.setSearchText,filteredTasks:r.filteredTasks,currentTask:x.currentTask,detailBody:x.detailBody,actionMsg:x.actionMsg,actionReasons:x.actionReasons,showDetail:L=>void x.showDetail(L),doAction:x.doAction,taskCost:x.taskCost,costBox:x.costBox,costSummary:x.costSummary,forkVisible:x.forkVisible,setForkVisible:x.setForkVisible,forkTask:x.forkTask,forkMsg:x.forkMsg,coordChildren:x.coordChildren,coordText:"",agents:x.agents,agentsNote:x.agentsNote,reviews:x.reviews,reviewMsg:x.reviewMsg,reviewError:x.reviewError,refreshReviews:x.refreshReviews,postReview:x.postReview,submitFindings:x.submitFindings,traceEntries:x.traceEntries,traceNote:x.traceNote,traceDone:x.traceDone,traceKind:x.traceKind,setTraceKind:x.setTraceKind,downloadTrace:x.downloadTrace,traceMsg:x.traceMsg,sendChatMessage:x.sendChatMessage,chatMsg:x.chatMsg,chatHistory:x.chatHistory,followups:x.followups,approvals:x.approvals,approvalMsg:x.approvalMsg,refreshApprovals:x.refreshApprovals,decideApproval:x.decideApproval,peerMessages:x.peerMessages,peerMsg:x.peerMsg,postPeer:x.postPeer,automations:_.automations,autoMsg:_.autoMsg,refreshAutomations:()=>void _.refreshAutomations(),createAutomation:_.createAutomation,cancelAutomation:_.cancelAutomation,triage:_.triage,triageError:_.triageError,refreshTriage:()=>void _.refreshTriage(),threadText:x.threadText,threadGateNote:x.threadGateNote,threadMsg:x.threadMsg,threadList:x.threadList,threadAction:x.threadAction,dispatch:async(L,dt)=>{const zt=await r.dispatch(L,dt);return r.refreshTasks(m.current),zt},dispatchMsg:"",refreshAll:tt,refreshSlow:at,refreshStamp:w}}function nu({label:i,value:r,sub:m}){return s.jsxs("div",{className:"dash-card data-card",children:[s.jsx("div",{className:"dash-card-label",children:i}),s.jsx("div",{className:"dash-card-value",children:r}),s.jsx("div",{className:"muted",children:m})]})}function ng(){const i=Mt(),r=i.healthText==="未加载"?"未加载":i.healthText.includes("worker_ok=true")?"正常":i.healthText.includes("worker_ok=false")?"异常":i.healthText.includes("加载失败")?"加载失败":"未知",m=i.quotaText.match(/剩余 \$([0-9.]+)/),o=i.quotaText.includes("加载失败")?"加载失败":i.quotaText.includes("未填 key")||i.quotaText==="未加载"?"未加载":m?"$"+m[1]:"配额",_=["running","completed","failed","queued","merged","interrupted"].map(b=>i.tasks.filter(B=>B.status===b).length).map((b,B)=>["running","completed","failed","queued","merged","interrupted"][B]+" "+b).join(" | "),C=i.projects.find(b=>b.id===i.projectId),N=i.taskError?{value:"加载失败",sub:i.taskError}:i.projectId?{value:String(i.tasks.length),sub:i.taskCountText+" | "+_+(C?" | "+C.name:"")}:{value:"先选项目",sub:i.projectMsg||"项目加载后自动选第一个"};let x;if(i.workersError)x={value:"加载失败",sub:i.workersError};else if(i.workers===null)x={value:i.workersSummary||"未加载",sub:"完整 worker 清单仅全局管理员可见"};else{const b=i.workers.filter(B=>{if(B.alive!==void 0&&B.alive!==null)return!!B.alive;const tt=kh(B).age;return tt!==null&&tt<=120}).length;x={value:b+" 在线 / "+i.workers.length,sub:i.workers.length-b+" 离线"}}const w=i.projectMsg.includes("加载失败")?{value:"加载失败",sub:i.projectMsg}:{value:i.projects.length+" 个",sub:C?"当前项目:"+C.name:"未选项目(加载后自动选第一个)"},U=[i.envMsg,i.memberError,i.skillError].filter(b=>b&&b.includes("失败")),G=i.projectId?U.length?{value:"部分加载失败",sub:U.join(" | ")}:{value:i.envs.length+" 个环境",sub:i.members.length+" 成员 | "+i.skills.length+" 技能 | "+i.apps.length+" 应用 | "+i.mcpServers.length+" MCP"}:{value:"先选项目",sub:"选项目后显示环境 / 成员 / 技能计数"};return s.jsxs("section",{className:"dash-cards","aria-label":"数据卡片",children:[s.jsx(nu,{label:"健康",value:r,sub:i.healthText}),s.jsx(nu,{label:"配额",value:o,sub:i.quotaText}),s.jsx(nu,{label:"任务",value:N.value,sub:N.sub}),s.jsx(nu,{label:"Workers",value:x.value,sub:x.sub}),s.jsx(nu,{label:"项目",value:w.value,sub:w.sub}),s.jsx(nu,{label:"项目数据",value:G.value,sub:G.sub})]})}function Qe({id:i,className:r,title:m,children:o}){return s.jsxs("section",{id:i,className:"card"+(r?" "+r:""),children:[m?s.jsx("h2",{children:m}):null,o]})}function Ut({children:i}){return s.jsx("div",{className:"bar",children:i})}function Ml({items:i,empty:r}){return i.length?s.jsx("ul",{className:"data-list",children:i.map((m,o)=>s.jsx("li",{children:m},o))}):s.jsx("div",{className:"muted",children:r||"(暂无)"})}function cu({children:i}){return s.jsx("ul",{className:"data-list",children:i})}function ug(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState(!1),[x,w]=v.useState(!1),[U,G]=v.useState(!1),[b,B]=v.useState("docker"),[tt,at]=v.useState(""),[et,L]=v.useState(""),[dt,zt]=v.useState(""),[Jt,nt]=v.useState(""),[Xt,te]=v.useState(""),[ct,yt]=v.useState(""),[re,he]=v.useState(""),Vt=v.useRef(null),Ft=v.useRef(null),le=v.useRef(null),[Ie,vt]=v.useState("");async function Y(){var Ue,_e,y;if(vt(""),!i.projectId){vt("先选项目");return}if(!r.trim()){vt("prompt 必填");return}const A={project_id:i.projectId,prompt:r.trim()};i.envSelect&&(A.environment_id=i.envSelect),b&&(A.executor=b);const lt=et.trim()||tt;lt&&(A.model=lt),dt&&(A.effort=dt);const gt=ct.trim()||Xt;if(gt&&(A.child_model=gt),re&&(A.child_effort=re),Jt&&(A.approval=Jt),U){if(Jt==="full"){vt("计划模式不能与完全访问同用");return}if(C||x){vt("计划模式不能与 goal 模式同用");return}A.plan=1}x?(A.goal_mode=1,A.no_time_limit=1):C&&(A.goal_mode=1);const St=o.trim();if(St){try{A.coordinator_parts=JSON.parse(St)}catch{vt("协调员子任务 JSON 解析失败");return}if(!Array.isArray(A.coordinator_parts)){vt("协调员子任务必须是数组");return}if(C||x||U){vt("协调员任务不能与 goal/计划模式同用:协调员任务本身不跑模型回合,请取消 goal/计划勾选,或清空协调员 JSON");return}}const ve=Fy(((Ue=Vt.current)==null?void 0:Ue.files)||null,((_e=Ft.current)==null?void 0:_e.files)||null,((y=le.current)==null?void 0:y.files)||null);try{const R=await i.dispatch(A,ve);vt(R),m(""),_(""),Vt.current&&(Vt.current.value=""),Ft.current&&(Ft.current.value=""),le.current&&(le.current.value="")}catch(R){vt("提交失败:"+((R==null?void 0:R.message)||String(R)))}}return s.jsxs(Qe,{id:"nav-newtask",className:"composer",title:"新建任务",children:[s.jsxs(Ut,{children:[s.jsxs("select",{"aria-label":"环境",value:i.envSelect,onChange:A=>i.setEnvSelect(A.target.value),children:[s.jsx("option",{value:"",children:"环境:不指定(走项目仓库)"}),i.envs.map(A=>s.jsxs("option",{value:A.id,disabled:A.status!=="ready",children:[A.name,"(",A.status,")"]},A.id))]}),s.jsxs("select",{"aria-label":"执行器",value:b,onChange:A=>B(A.target.value),children:[s.jsx("option",{value:"docker",children:"docker(默认,多用户下隔离最强)"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"cloud",children:"cloud"})]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:C,onChange:A=>N(A.target.checked)})," goal 模式"]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:x,onChange:A=>w(A.target.checked)})," goal 模式无敌版"]}),s.jsxs("label",{children:[s.jsx("input",{type:"checkbox",checked:U,onChange:A=>G(A.target.checked)})," 计划模式(只读)"]})]}),s.jsx("textarea",{className:"prompt stacked",placeholder:"任务 prompt(必填)",value:r,onChange:A=>m(A.target.value)}),s.jsx("textarea",{className:"coord stacked",placeholder:"协调员子任务 JSON(可选),留空为普通任务",value:o,onChange:A=>_(A.target.value)}),s.jsxs("div",{className:"muted",children:["协调员格式:[","{",'"name":"后端","prompt":"做后端"',"}",",","{",'"name":"前端","prompt":"做前端"',"}","];提交后 worker 并行建子任务、等齐、合流汇总。不能与 goal/计划模式同用。协调员与 goal/计划互斥:勾了 goal 或计划模式时不要填协调员 JSON,提交前会校验并拦截。子任务费用记父任务创建人账;父任务创建时按分工数预留配额,余额不足时整个父任务被挡下。"]}),s.jsxs(Ut,{children:[s.jsxs("select",{"aria-label":"模型",value:tt,onChange:A=>at(A.target.value),children:[s.jsx("option",{value:"",children:"模型:默认(跟随配置)"}),i.models.map(A=>s.jsx("option",{value:A,children:A},A))]}),i.modelCustomVisible?s.jsx("input",{type:"text",placeholder:"手动输入模型(中转列表取不到时用)",value:et,onChange:A=>L(A.target.value)}):null,s.jsxs("select",{"aria-label":"推理强度",value:dt,onChange:A=>zt(A.target.value),children:[s.jsx("option",{value:"",children:"推理强度:默认(跟随配置)"}),Yh.map(A=>s.jsx("option",{value:A,children:A},A))]}),s.jsxs("select",{"aria-label":"权限",value:Jt,onChange:A=>nt(A.target.value),children:[s.jsx("option",{value:"",children:"权限:默认(跟随配置)"}),s.jsx("option",{value:"ask",children:"请求批准"}),s.jsx("option",{value:"auto",children:"帮我批准"}),s.jsx("option",{value:"full",children:"完全访问"})]})]}),s.jsxs(Ut,{children:[s.jsxs("select",{"aria-label":"子任务模型",value:Xt,onChange:A=>te(A.target.value),children:[s.jsx("option",{value:"",children:"子任务模型:跟随本任务模型"}),i.models.map(A=>s.jsx("option",{value:A,children:A},A))]}),s.jsx("input",{type:"text",placeholder:"子任务模型手动输入(中转列表里没有时填,如 gpt-6-luna;留空=跟随本任务模型)",value:ct,onChange:A=>yt(A.target.value)}),s.jsxs("select",{"aria-label":"子任务强度",value:re,onChange:A=>he(A.target.value),children:[s.jsx("option",{value:"",children:"子任务强度:跟随本任务强度"}),Yh.map(A=>s.jsx("option",{value:A,children:A},A))]})]}),s.jsx("div",{className:"muted",children:"子任务模型/强度是派生默认:本任务用 marker task-create 或协调员分工派生的子任务,未显式写模型/强度时用它;块/分工里显式写了则覆盖它。也可以不在这里填、直接在 prompt 里写“子任务用 gpt-6-luna max”,建任务时服务端会解析成同一对字段(任务详情里可核对)。"}),C?s.jsx("div",{className:"muted",children:"goal 模式:输入框内容即目标,不需要专用 prompt 与验收命令;不限轮次,模型确认达成后在回复末尾输出“目标已达成”即结束,未达成会一直运行,可用取消停止。"}):null,x?s.jsx("div",{className:"muted",children:"goal 模式无敌版:goal 模式 + 任务不限时(去掉 worker/docker 总超时;单轮 600 秒护栏还在,不限的是任务总时长与总轮次)。服务端默认的自动续跑与断点镜像同时生效。"}):null,s.jsxs(Ut,{children:[s.jsx("span",{className:"muted",children:"附件(放进任务工作区,图片与普通文件不区分):"}),s.jsx("input",{ref:Vt,type:"file",multiple:!0,title:"文件"}),s.jsx("input",{ref:Ft,type:"file",multiple:!0,title:"文件夹",webkitdirectory:""}),s.jsx("input",{ref:le,type:"file",accept:"image/*",multiple:!0,title:"图片"})]}),s.jsxs(Ut,{children:[s.jsx("button",{className:"seal",onClick:Y,children:"提交任务"}),s.jsx("span",{className:"muted",children:Ie||i.dispatchMsg})]})]})}function Qh(i){const r=(i.prompt||"").trim();return r?[...r][0]:i.id?[...i.id][0]:"?"}function zc(i){const r=Math.max(0,Math.floor(i));if(r<60)return r+"秒";if(r<3600){const _=Math.floor(r/60),C=r%60;return C?_+"分"+C+"秒":_+"分"}if(r<86400){const _=Math.floor(r/3600),C=Math.floor(r%3600/60);return C?_+"小时"+C+"分":_+"小时"}const m=Math.floor(r/86400),o=Math.floor(r%86400/3600);return o?m+"天"+o+"小时":m+"天"}function iu(i){if(i==null)return null;const r=Number(i);return Number.isFinite(r)?r:null}function Xh(i){const r=Date.now()/1e3,m=iu(i.started_at),o=iu(i.finished_at),_=iu(i.created_at);return m!==null&&o!==null&&o>=m?[zc(o-m),"总耗时:开始→结束(末次认领的执行时长)"]:m!==null&&i.status==="running"?["进行中 "+zc(r-m),"总耗时:进行中,已用时长从开始算起,随刷新更新"]:_!==null&&o!==null&&o>=_?[zc(o-_),"总耗时:创建→完成(含排队等待;无开始时间时的兜底口径)"]:_!==null&&(i.status==="queued"||i.status==="running")?[(i.status==="queued"?"排队中 ":"进行中 ")+zc(r-_),"总耗时:从创建算起的已用时长(无开始时间时的兜底口径)"]:["—","总耗时:无可用时间戳"]}function ig(i){if(i==null||!Number.isFinite(Number(i)))return"—";const r=Number(i)/1e6;return"$"+(r>0&&r<.01?r.toFixed(4):r.toFixed(2))}function Vh(i){const r=iu(i.total_tokens);if(r!==null)return[r.toLocaleString()+" token","token:服务端 total_tokens"];const m=iu(i.actual_tokens),o=iu(i.estimated_tokens);return m!==null||o!==null?[((m||0)+(o||0)).toLocaleString()+" token","token:actual + estimated 分项加总"]:["token —","token:本任务对象未带 token 字段;单任务真数在详情的成本里可查,不逐个调成本接口、不编造"]}function cg({onNew:i}){const r=Mt();return s.jsxs("div",{children:[s.jsxs("div",{className:"search-box",children:[s.jsxs("svg",{viewBox:"0 0 24 24",width:"18",height:"18",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round","aria-hidden":"true",children:[s.jsx("circle",{cx:"11",cy:"11",r:"7"}),s.jsx("path",{d:"M21 21l-4.3-4.3"})]}),s.jsx("input",{type:"text",placeholder:"搜索","aria-label":"搜索任务",value:r.searchText,onChange:m=>r.setSearchText(m.target.value)})]}),s.jsx("div",{className:"bar",children:s.jsxs("select",{"aria-label":"项目",value:r.projectId,onChange:m=>r.selectProject(m.target.value),children:[r.projects.length===0?s.jsx("option",{value:"",children:"(先加载项目)"}):null,r.projects.map(m=>s.jsxs("option",{value:m.id,children:[m.name," (",De(m.id),")"]},m.id))]})}),s.jsxs("div",{className:"list-section-head",children:[s.jsx("span",{children:"主要聊天"}),s.jsx("button",{type:"button","aria-label":"派发新任务",title:"派发新任务",onClick:i,children:"+"})]}),s.jsxs("div",{className:"bar",children:[s.jsxs("select",{"aria-label":"状态筛选",value:r.statusFilter,onChange:m=>r.setStatusFilter(m.target.value),children:[s.jsx("option",{value:"",children:"状态:全部"}),["queued","running","completed","failed","interrupted","merged","merge-failed"].map(m=>s.jsx("option",{value:m,children:m},m))]}),s.jsxs("select",{"aria-label":"执行器筛选",value:r.executorFilter,onChange:m=>r.setExecutorFilter(m.target.value),children:[s.jsx("option",{value:"",children:"执行器:全部"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"docker",children:"docker"}),s.jsx("option",{value:"cloud",children:"cloud"})]})]}),s.jsxs("div",{className:"bar",children:[s.jsx("button",{onClick:r.refreshTasks,children:"刷新"}),s.jsx("span",{className:"muted",children:r.taskCountText})]}),r.taskError?s.jsx("div",{className:"err",children:r.taskError}):r.projectId?r.filteredTasks.length===0?s.jsx("div",{className:"muted",children:r.tasks.length?"没有符合筛选条件的任务":"该项目暂无任务"}):s.jsx("ul",{className:"issue-list",children:r.filteredTasks.slice().reverse().map(m=>{var w;const[o,_]=Xh(m),[C,N]=Vh(m),x=Qh(m);return s.jsxs("li",{className:"issue-item"+(((w=r.currentTask)==null?void 0:w.id)===m.id?" selected":""),onClick:()=>r.showDetail(m.id),children:[s.jsx("span",{className:"issue-state st-"+m.status,"aria-hidden":"true"}),s.jsx("span",{className:"issue-first",title:"任务首字:"+x,"aria-hidden":"true",children:x}),s.jsxs("span",{style:{flex:1,minWidth:0},children:[s.jsxs("div",{className:"issue-title",children:[m.plan?"[计划] ":"",m.forked_from?"[分支] ":"",m.coordinator_parts?"[协调] ":"",m.parent_task_id?"[协调子任务] ":"",String(m.prompt||De(m.id)).slice(0,60)]}),s.jsxs("div",{className:"issue-meta",children:[De(m.id)," · ",s.jsx("span",{className:"st-"+m.status,children:m.status})," · ",m.executor||"",m.updated_at?" · "+new Date(m.updated_at*1e3).toLocaleString():""," · ",s.jsxs("span",{title:_,children:["耗时 ",o]})," · ",s.jsx("span",{title:N,children:C})]})]})]},m.id)})}):s.jsx("div",{className:"muted",children:"先选项目"})]})}function sg(i){const r=v.useRef(null),[m,o]=v.useState(!0),_=v.useRef(!0),C=()=>{const N=r.current;if(!N)return;const x=N.scrollHeight-N.scrollTop-N.clientHeight<80;_.current=x,o(x)};return v.useEffect(()=>{_.current&&r.current&&(r.current.scrollTop=r.current.scrollHeight)},[i]),{ref:r,following:m,onScroll:C}}function fg({msg:i}){if(i.role==="status")return s.jsx("div",{className:"chat-status",children:i.text});const r=i.label||(i.role==="user"?"用户":i.role==="assistant"?"助手":"工具");return s.jsxs("div",{className:"gh-comment "+i.role,children:[s.jsx("div",{className:"gh-comment-header",children:s.jsx("span",{className:"gh-comment-author",children:r})}),s.jsx("div",{className:"gh-comment-body",children:i.text})]})}function Lh({messages:i,empty:r}){const{ref:m,following:o,onScroll:_}=sg(i.length);return s.jsxs("div",{className:"chat-list",ref:m,onScroll:_,children:[i.length===0?s.jsx("div",{className:"muted",children:r||"(暂无消息)"}):i.map(C=>s.jsx(fg,{msg:C},C.id)),!o&&i.length>0?s.jsx("button",{className:"chat-follow",onClick:()=>{m.current&&(m.current.scrollTop=m.current.scrollHeight)},children:"回到最新 ↓"}):null]})}function rg({onSend:i,disabled:r,placeholder:m}){const[o,_]=v.useState(""),C=()=>{const N=o.trim();!N||r||(i(N),_(""))};return s.jsxs("div",{className:"gh-comment-box",children:[s.jsx("textarea",{"aria-label":"会话输入",rows:3,placeholder:m||"消息",value:o,disabled:r,onChange:N=>_(N.target.value),onKeyDown:N=>{N.key==="Enter"&&!N.shiftKey&&(N.preventDefault(),C())}}),s.jsx("div",{className:"gh-comment-footer",children:s.jsx("button",{type:"button",className:"primary","aria-label":"发送",disabled:r||!o.trim(),onClick:C,children:"发送"})})]})}function Zh(i,r){const m=i.id||"trace-"+r;if(i.kind==="message")return{id:m,role:"assistant",text:(i.phase?"["+i.phase+"] ":"")+(i.text||""),label:"助手"};if(i.kind==="exec"||i.kind==="file"||i.kind==="tool"||i.kind==="call"){const o=i.kind==="exec"?"命令":i.kind==="file"?"文件":i.kind==="tool"?"工具":"调用";return{id:m,role:"tool",text:dr(i),label:o}}return i.kind==="plan"?{id:m,role:"status",text:i.text||""}:i.kind==="reasoning"?{id:m,role:"status",text:"思考:"+(i.summary||"")}:i.kind==="agent-start"?{id:m,role:"status",text:"子代理开始:"+(i.name||"")+(i.prompt?"("+i.prompt+")":"")}:i.kind==="agent-done"?{id:m,role:"status",text:"子代理结束:"+(i.name||"")+" "+(i.status||"")}:{id:m,role:"status",text:dr(i)}}function og(){const i=Mt(),r=v.useMemo(()=>{const m=i.currentTask,o=m&&m.prompt?[{id:"task-prompt",role:"user",text:m.prompt}]:[],C=(i.traceKind?i.traceEntries.filter(x=>x.kind===i.traceKind):i.traceEntries).map((x,w)=>Zh(x,w)),N=i.traceDone?[{id:"trace-done",role:"status",text:"链路已结束("+i.traceDone+")"}]:[];return[...o,...C,...N]},[i.currentTask,i.traceEntries,i.traceKind,i.traceDone]);return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"muted",children:"实时链路"}),s.jsxs(Ut,{children:[s.jsxs("select",{"aria-label":"链路类型",value:i.traceKind,onChange:m=>i.setTraceKind(m.target.value),children:[s.jsx("option",{value:"",children:"链路类型:全部"}),["exec","file","call","tool","message","reasoning","plan","agent-start","agent-done"].map(m=>s.jsx("option",{value:m,children:m==="exec"?"命令":m==="file"?"文件":m==="call"?"调用":m==="tool"?"工具":m==="message"?"消息":m==="reasoning"?"思考":m==="plan"?"计划":"子代理"},m))]}),s.jsx("button",{onClick:i.downloadTrace,children:"下载完整链路"}),s.jsx("span",{className:"muted",children:i.traceMsg})]}),i.traceNote?s.jsx("div",{children:s.jsx("span",{className:"err",children:i.traceNote})}):null,s.jsx("div",{className:"chat-column",children:s.jsx(Lh,{messages:r,empty:"(暂无链路条目)"})}),s.jsx("div",{className:"muted",children:"对话时间线:首条是本任务 prompt(用户);助手回复来自 message 条目,命令/文件/工具/调用是工具评论框,计划/思考/子代理开始结束是时间线上的状态文字。流式进行中时新条目实时追加;你在底部时自动跟随,往上翻时暂停跟随,点“回到最新”恢复。"})]})}function dg(){const i=Mt(),r=i.currentTask,m=v.useMemo(()=>{if(!r)return[];if(i.chatHistory)return i.chatHistory.messages.map(b=>({id:b.id,role:b.role,text:b.text,label:b.label}));const w=r.prompt?[{id:"task-prompt",role:"user",text:r.prompt}]:[],U=i.traceEntries.filter(b=>b.kind==="message").map((b,B)=>Zh(b,B)),G=i.followups.map((b,B)=>({id:"followup-"+B,role:"user",text:String(b.body||""),label:"后续消息"}));return[...w,...U,...G]},[r,i.chatHistory,i.traceEntries,i.followups]);if(!r)return s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示继续会话"});const o=uu.includes(r.status),_=["queued","running"].includes(r.status),C=o||_,N=o?"终态任务:发送走继续接口(同一会话再跑一轮)":_?"运行中/排队中:发送走后续消息直接发送(跑完当前轮后优先执行)":"merged/merge-failed 任务不可继续,也不可发后续消息",x=i.chatHistory?i.chatHistory.legacy_continue_count??null:null;return s.jsxs("div",{className:"chat-column",children:[x!==null&&x>0?s.jsxs("div",{className:"muted",children:["此前有 ",x," 条继续消息发生在持久化之前,未入库,上面历史不完整;部署后新发的继续消息会正常显示。"]}):null,i.chatHistory&&i.chatHistory.trace_note?s.jsx("div",{className:"muted",children:i.chatHistory.trace_note}):null,s.jsx(Lh,{messages:m,empty:"(暂无会话消息)"}),s.jsx(rg,{disabled:!C,placeholder:"消息",onSend:w=>void i.sendChatMessage(w)}),s.jsxs("div",{className:"muted",children:[N,"。",i.chatMsg]})]})}function mg(){return Mt().currentTask?s.jsxs("div",{className:"conversation",children:[s.jsx(og,{}),s.jsx("div",{className:"conv-divider"}),s.jsx(dg,{})]}):s.jsx("div",{className:"conversation",children:s.jsx("div",{className:"muted",children:"在任务列表里点一条任务,对话和详情就切到该任务;也可以在上面派发一个新任务。"})})}function hg(){const i=Mt(),r=i.currentTask,[m,o]=v.useState("");if(!r)return null;const _=uu.includes(r.status),C=["failed","interrupted","merge-failed"].includes(r.status);return s.jsxs(s.Fragment,{children:[s.jsxs(Ut,{children:[s.jsx("button",{disabled:!C,title:C?"":"仅 failed/interrupted/merge-failed 可重试",onClick:()=>i.doAction("retry"),children:"重试"}),s.jsx("button",{className:"danger",disabled:_,title:_?"终态任务不可取消":"",onClick:()=>i.doAction("cancel"),children:"取消"}),s.jsx("button",{disabled:r.status!=="completed",title:r.status!=="completed"?"仅 completed 可合并":"",onClick:()=>i.doAction("merge"),children:"合并(completed → merged)"}),s.jsx("button",{disabled:r.status!=="merged",title:r.status!=="merged"?"仅 merged 可提 PR":"",onClick:()=>i.doAction("pr"),children:"提 PR(须 merged)"}),_?s.jsx("button",{onClick:()=>i.setForkVisible(!0),children:"分支"}):null,s.jsx("button",{onClick:i.taskCost,children:"查成本"}),s.jsxs("span",{className:"muted",children:[i.actionMsg," ",i.actionReasons]})]}),i.forkVisible?s.jsxs("div",{children:[s.jsx("input",{type:"text",placeholder:"分支首轮消息(必填,带历史的新会话)",style:{width:"100%",boxSizing:"border-box",margin:"6px 0"},value:m,onChange:N=>o(N.target.value)}),s.jsxs(Ut,{children:[s.jsx("button",{className:"seal",onClick:async()=>{await i.forkTask(m),o("")},children:"创建分支任务"}),s.jsx("span",{className:"muted",children:i.forkMsg})]})]}):null]})}function vg(){const i=Mt(),[r,m]=v.useState("uncommittedChanges"),[o,_]=v.useState(""),[C,N]=v.useState(""),[x,w]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("h3",{children:"评审队列"}),s.jsxs("select",{"aria-label":"评审目标",value:r,onChange:U=>m(U.target.value),children:[s.jsx("option",{value:"uncommittedChanges",children:"未提交改动(工作区)"}),s.jsx("option",{value:"baseBranch",children:"与分支的差异"}),s.jsx("option",{value:"commit",children:"指定提交"}),s.jsx("option",{value:"custom",children:"自定义评审指令"})]}),s.jsx("input",{className:"stacked",placeholder:"与分支的差异用:分支名(如 main)",style:{width:"100%"},value:o,onChange:U=>_(U.target.value)}),s.jsx("input",{className:"stacked",placeholder:"指定提交用:提交 sha",style:{width:"100%"},value:C,onChange:U=>N(U.target.value)}),s.jsx("textarea",{placeholder:"自定义评审指令用:评审指令正文",value:x,onChange:U=>w(U.target.value)}),s.jsxs(Ut,{children:[s.jsx("button",{className:"primary",onClick:()=>void i.postReview({target_type:r,branch:o.trim()||void 0,sha:C.trim()||void 0,instructions:x.trim()||void 0}),children:"登记评审需求"}),s.jsx("button",{onClick:i.refreshReviews,children:"刷新队列"}),s.jsx("span",{className:"muted",children:i.reviewMsg})]}),s.jsx("div",{className:"muted",children:"本基线只登记评审需求(requested),不自动跑评审;评审是否执行、结果如何,以评审队列里的记录为准。"}),i.reviewError?s.jsx("div",{className:"muted",children:i.reviewError}):i.reviews.length===0?s.jsx("div",{className:"muted",children:"点任务行查看详情后,点“刷新队列”查看评审记录"}):s.jsx(cu,{children:i.reviews.map(U=>{let G=U.target_type||"";return U.branch&&(G+=":"+U.branch),U.sha&&(G+=":"+String(U.sha).slice(0,12)),U.instructions&&(G+=":"+String(U.instructions).slice(0,80)),s.jsxs("li",{children:[s.jsxs("span",{className:"row-main",children:[s.jsx("b",{children:"评审"})," ",De(U.id)," | ",G," | ",s.jsx("span",{className:"st-"+(U.status||""),children:U.status}),U.created_at?" | "+Ga(U.created_at):"",s.jsx("br",{}),U.findings?String(U.findings).slice(0,1e3):s.jsx("span",{className:"muted",children:"(暂无 findings:评审尚未执行或尚未写回)"})]}),s.jsx("button",{onClick:()=>i.submitFindings(U.id),children:"写 findings"})]},U.id)})})]})}function yg(){const i=Mt();return i.currentTask?i.currentTask.coordinator_parts?i.coordChildren.length===0?s.jsx("div",{className:"muted",children:"(子任务尚未创建)"}):s.jsx(cu,{children:i.coordChildren.map(r=>s.jsx("li",{children:s.jsxs("span",{className:"row-main",children:["分工 ",s.jsx("b",{children:r.coordinator_part||""})," | 状态 ",s.jsx("span",{className:"st-"+r.status,children:r.status})," | ",De(r.id)," | ",String(r.prompt||"").slice(0,60)]})},r.id))}):s.jsx("div",{className:"muted",children:"(非协调员任务)"}):s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示协调员的子任务"})}function gg(){const i=Mt();if(!i.currentTask)return s.jsx("div",{className:"muted",children:"点任务行查看详情后,这里显示子代理链路"});if(i.agents.length===0)return s.jsxs("div",{className:"muted",children:["(暂无子代理)",i.agentsNote?s.jsx("span",{className:"err",children:i.agentsNote}):null]});const r={main:"主任务",delegate:"委派子任务",model:"模型子代理"},m={running:"进行中",completed:"已完成",failed:"失败",interrupted:"已中断",unknown:"未知"};return s.jsx(cu,{children:i.agents.map((o,_)=>s.jsx("li",{children:s.jsxs("span",{className:"row-main",children:[s.jsxs("b",{children:[r[o.kind||""]||o.kind||"",":"]}),o.name||""," ",s.jsx("span",{className:"st-"+(o.status||""),children:m[o.status||""]||o.status||"?"})," | 过程调用 "+(o.calls?o.calls.length:0)+" 条",o.updated_ts?" | 最近活动 "+Ga(o.updated_ts/1e3):"",o.prompt?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsxs("span",{className:"muted",children:["任务:",o.prompt]})]}):null,o.calls&&o.calls.length?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),o.calls.slice(-50).map((C,N)=>s.jsx("div",{children:dr(C)},N))]}):s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsx("span",{className:"muted",children:"(暂无过程调用)"})]})]})},_))})}function Sg(){const i=Mt();return s.jsxs(s.Fragment,{children:[s.jsxs(Ut,{children:[s.jsx("button",{onClick:i.refreshApprovals,children:"刷新审批队列"}),s.jsx("span",{className:"muted",children:i.approvalMsg})]}),s.jsx("div",{className:"muted",children:"待审批项需人工点记录允许或记录拒绝;超时默认拒绝。当前版本只留回执,不拦截实时行为(实时请求的事前拦截待 host 接入后生效,在此之前实时行为不变)。"}),s.jsx(Ml,{empty:"(暂无审批项)",items:i.approvals.map(r=>s.jsxs("span",{className:"row-main",children:["[",r.kind,"|",r.status,"] ",r.summary,["approved","denied","expired"].includes(r.status||"")?"|回执:"+(r.decision||r.status)+" by "+String(r.decided_by||"").slice(0,8)+" "+Ga(r.decided_at):"",r.status==="pending"?s.jsxs(s.Fragment,{children:[" ",s.jsx("button",{onClick:()=>i.decideApproval(r.id,"approved"),children:"记录允许"})," ",s.jsx("button",{onClick:()=>i.decideApproval(r.id,"denied"),children:"记录拒绝"})]}):null]},r.id))})]})}function pg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("input",{placeholder:"目标任务 id(与本任务同项目;对方运行中排队执行、已终态则续跑复活,绝不打断当前轮)",style:{width:"100%"},value:r,onChange:C=>m(C.target.value)}),s.jsx("textarea",{placeholder:"消息正文(以本任务名义发出;对方 agent 会看到发送方任务 id,可照此回消息)",value:o,onChange:C=>_(C.target.value)}),s.jsxs(Ut,{children:[s.jsx("button",{onClick:async()=>{await i.postPeer("queued",r,o),_("")},children:"排队发给对方"}),s.jsx("button",{className:"primary",onClick:async()=>{await i.postPeer("direct",r,o),_("")},children:"直接发送"}),s.jsx("span",{className:"muted",children:i.peerMsg})]}),s.jsx(Ml,{empty:"(本任务尚未发出任务间消息)",items:i.peerMessages.map((C,N)=>s.jsxs("span",{className:"row-main",children:["[发给 ",String(C.task_id).slice(0,8),"|",C.mode,"|",C.status,"] ",String(C.body||"").slice(0,120)]},N))})]})}function bg(){const i=Mt(),[r,m]=v.useState(""),o=i.currentTask?["completed","failed","interrupted"].includes(i.currentTask.status):!1;return s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"muted",children:i.threadText||"点任务行查看详情后,这里显示线程元数据"}),s.jsxs(Ut,{children:[s.jsx("input",{type:"text",placeholder:"新线程名",value:r,onChange:_=>m(_.target.value)}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("rename",r),children:"重命名"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("archive",""),children:"归档"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("unarchive",""),children:"取消归档"}),s.jsx("button",{disabled:!o,onClick:()=>i.threadAction("compact",""),children:"压缩"}),s.jsx("span",{className:"muted",children:i.threadGateNote}),s.jsx("span",{className:"muted",children:i.threadMsg})]}),s.jsx(Ml,{empty:"暂无其他线程",items:i.threadList.map((_,C)=>s.jsxs("span",{className:"row-main",children:[_.name||_.thread_name||_.id||""," [",_.id||"","]",_.archived?" [已归档]":"",_.cwd?" "+_.cwd:""]},C))}),s.jsx("div",{className:"muted",children:"限制:Docker/异机任务线程操作一律 409;merged/merge-failed 不可改;turn/steer 与 review/start 不在本批。"})]})}function xg(){const i=Mt(),r=i.currentTask;if(!r)return s.jsx(Qe,{id:"nav-detail",title:"任务详情",children:s.jsx("div",{className:"muted",children:"点任务行查看详情"})});const[m,o]=Xh(r),[_,C]=Vh(r),N=Qh(r);return s.jsxs(Qe,{id:"nav-detail",title:"任务详情",children:[s.jsxs("div",{children:["状态 ",s.jsx("b",{className:"st-"+r.status,children:r.status}),"(",Vy[r.status]||"未知状态",")",s.jsx("br",{}),s.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6},children:[s.jsx("span",{className:"issue-first",title:"任务首字:"+N,"aria-hidden":"true",children:N}),s.jsxs("span",{title:o,children:["耗时 ",m]}),s.jsx("span",{children:" · "}),s.jsx("span",{title:C,children:_})]}),s.jsx("br",{}),i.costSummary===void 0?s.jsx("span",{className:"muted",children:"成本加载中…"}):i.costSummary===null?s.jsx("span",{className:"muted",children:"成本明细加载失败(“查成本”按钮仍可手动拉取原始 JSON)"}):s.jsxs("span",{title:"成本明细:GET /tasks/{id}/cost 聚合;美元只计有价行,无价 token 单列;缓存是输入 token 的子集,不另计",children:["成本 ",ig(i.costSummary.usd_micros)," | token ",(i.costSummary.total_tokens??0).toLocaleString(),"(实际 ",(i.costSummary.actual_tokens??0).toLocaleString()," / 估算 ",(i.costSummary.estimated_tokens??0).toLocaleString(),",缓存 ",(i.costSummary.cached_input_tokens??0).toLocaleString(),",无价 ",(i.costSummary.unpriced_actual_tokens??0).toLocaleString(),")| 轮数 ",i.costSummary.turns??0," | fallback ",i.costSummary.fallback_count??0]}),s.jsx("br",{}),"任务 ",r.id," | turn ",De(r.turn_id)," | root turn ",De(r.root_turn_id),s.jsx("br",{}),"executor ",r.executor||""," | 主机 ",r.worktree_host||"",s.jsx("br",{}),"模型 ",r.model||"默认"," | 强度 ",r.effort||"默认",r.child_model||r.child_effort?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"子任务默认 ",(r.child_model||"跟随本任务")+" / "+(r.child_effort||"跟随本任务")]}):null,s.jsx("br",{}),"权限 ",r.approval||"默认"," | 项目 ",De(r.project_id),s.jsx("br",{}),"更新 ",Ga(r.updated_at),r.plan?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"计划模式(只读)"]}):null,r.forked_from?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"分支自 ",De(r.forked_from)]}):null,r.goal_mode?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),r.no_time_limit?"goal 模式无敌版(不限时)":"goal 模式(不限轮次,模型宣告完成)"]}):r.verify_command?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"goal 模式(旧语义,验收命令)"]}):null,r.coordinator_parts?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"协调员:",r.coordinator_parts.length," 个子任务(",r.coordinator_parts.map(x=>x.name).join("、"),")"]}):null,r.parent_task_id?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"协调子任务,父任务 ",De(r.parent_task_id),r.coordinator_part?"("+r.coordinator_part+")":""]}):null,r.attachments&&r.attachments.length?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),"附件:",r.attachments.join("、")]}):null,r.pr_url?s.jsxs(s.Fragment,{children:[s.jsx("br",{}),s.jsxs("a",{href:r.pr_url,target:"_blank",rel:"noopener noreferrer",children:["PR #",r.pr_number]})]}):null,s.jsx("br",{}),"prompt:",r.prompt||""]}),s.jsx(hg,{}),s.jsx("pre",{children:i.detailBody||"(暂无 result/error 输出)"}),i.costBox?s.jsx("pre",{children:i.costBox}):null,s.jsx("h3",{children:"协调子任务"}),s.jsx(yg,{}),s.jsx("h3",{children:"子代理链路"}),s.jsx(gg,{}),s.jsx("h3",{children:"评审队列"}),s.jsx(vg,{}),s.jsx("h3",{children:"运行时审批队列"}),s.jsx(Sg,{}),s.jsx("h3",{children:"给其他任务发消息"}),s.jsx(pg,{}),s.jsx("h3",{children:"线程"}),s.jsx(bg,{})]})}function jg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState([]),[x,w]=v.useState(null),[U,G]=v.useState(!1),[b,B]=v.useState(""),[tt,at]=v.useState(""),et=v.useCallback(async()=>{if(!i.keySaved){N([]);return}try{const nt=await P($.userKeys);N(nt.keys||[]),at("")}catch(nt){at(nt instanceof Error?nt.message:"加载 key 列表失败")}},[i.keySaved]);v.useEffect(()=>{et()},[et]);const L=async()=>{B(""),at(""),G(!1);try{const nt=await P($.userKeys,"POST",{label:o.trim()||"api-key"});w(nt),_(""),B("新 key 已生成,只显示一次:复制后请妥善保存。"),await et()}catch(nt){at(nt instanceof Error?nt.message:"生成 key 失败")}},dt=async()=>{if(x)try{await navigator.clipboard.writeText(x.api_key),G(!0)}catch{at("复制失败:请手动选中上方 key 文本复制")}},zt=()=>{x&&(i.saveKeyInput(x.api_key),w(null),B("已存为当前浏览器 key(原有 key 未被撤销,需要时可单独撤销)。"))},Jt=async nt=>{const Xt=(()=>{try{return bl().slice(-4)}catch{return""}})(),te=nt.id==="legacy"?"(主 key:撤销后当前浏览器保存的 key 也可能随之失效,需重新登录拿新 key)":nt.hint&&nt.hint===Xt?"(这就是本浏览器当前在用的 key,撤销后本页会立刻未连接)":"";if(window.confirm(`撤销 key「${nt.label}」(后 4 位 ${nt.hint||"无"})吗?${te}撤销不可恢复。`)){B(""),at("");try{await P($.userKey(nt.id),"DELETE"),B(`已撤销 key「${nt.label}」。`),await et()}catch(ct){at(ct instanceof Error?ct.message:"撤销失败")}}};return s.jsxs(Qe,{id:"nav-key",title:"API Key",children:[s.jsxs(Ut,{children:[s.jsx("input",{type:"password",placeholder:"粘贴你的 X-API-Key(与调 API 用的同一个)",autoComplete:"off",value:r,onChange:nt=>m(nt.target.value)}),s.jsx("button",{className:"primary",onClick:()=>{i.saveKeyInput(r),m("")},children:"保存到本浏览器"}),s.jsx("button",{onClick:i.clearKeyInput,children:"清除"}),s.jsx("span",{className:"muted",children:i.keyState})]}),s.jsx("div",{children:s.jsx("span",{className:"muted",children:i.quotaText})}),!i.keySaved&&s.jsx("div",{children:s.jsx("span",{className:"muted",children:"先粘贴并保存已有 key,再生成或管理 key(生成接口本身也要用已有 key 鉴权)。"})}),i.keySaved&&s.jsxs(s.Fragment,{children:[s.jsxs(Ut,{children:[s.jsx("input",{placeholder:"新 key 备注(可选,默认 api-key,如 harness2-temp)",autoComplete:"off",value:o,onChange:nt=>_(nt.target.value)}),s.jsx("button",{className:"primary",onClick:()=>void L(),children:"生成新 key"}),s.jsx("button",{onClick:()=>void et(),children:"刷新列表"})]}),x&&s.jsxs("div",{children:[s.jsx("div",{children:s.jsxs("span",{className:"muted",children:["新 key(",x.label,",后 4 位 ",x.hint,"):只显示一次,关闭后无法再查看。"]})}),s.jsxs(Ut,{children:[s.jsx("input",{type:"text",readOnly:!0,value:x.api_key,onFocus:nt=>nt.target.select()}),s.jsx("button",{className:"primary",onClick:()=>void dt(),children:U?"已复制":"复制"}),s.jsx("button",{onClick:zt,children:"存为当前浏览器 key"}),s.jsx("button",{onClick:()=>w(null),children:"关闭(不再显示)"})]})]}),b&&s.jsx("div",{children:s.jsx("span",{className:"muted",children:b})}),tt&&s.jsx("div",{children:s.jsx("span",{children:tt})}),s.jsxs("div",{children:[C.length===0&&s.jsx("span",{className:"muted",children:"暂无 key(或列表加载失败,见上方报错)。"}),C.map(nt=>s.jsxs("div",{children:[s.jsx("span",{children:nt.label})," ",s.jsxs("span",{className:"muted",children:["后 4 位 ",nt.hint||"无"," · 创建 ",Ga(nt.created_at)," · 最近使用 ",nt.last_used_at?Ga(nt.last_used_at):"未使用过"]})," ",nt.revoked_at?s.jsxs("span",{className:"muted",children:["已撤销(",Ga(nt.revoked_at),")"]}):s.jsx("button",{onClick:()=>void Jt(nt),children:"撤销"})]},nt.id))]})]})]})}function Tg(){const i=Mt();return s.jsxs(Qe,{id:"adminCard",title:s.jsxs(s.Fragment,{children:["管理区 ",s.jsx("span",{className:"muted",children:"(仅全局管理员)"})]}),children:[s.jsx("div",{className:"muted",children:i.adminGate}),i.adminBody?s.jsxs(s.Fragment,{children:[s.jsxs(Ut,{children:[s.jsx("input",{type:"text",placeholder:"要查配额的用户 id",value:i.adminUserId,onChange:r=>i.setAdminUserId(r.target.value)}),s.jsx("button",{onClick:i.adminQuota,children:"查该用户配额"})]}),s.jsxs(Ut,{children:[s.jsx("button",{onClick:i.adminSweep,children:"手动触发 sweep(清理陈旧 running 任务)"}),s.jsx("button",{onClick:i.adminBackup,children:"手动触发备份"})]}),s.jsx("div",{className:"muted",children:i.adminResult})]}):null]})}function _g(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState("");return s.jsxs(Qe,{id:"nav-projects",title:"项目",children:[s.jsxs(Ut,{children:[s.jsxs("select",{"aria-label":"项目",value:i.projectId,onChange:x=>i.selectProject(x.target.value),children:[i.projects.length===0?s.jsx("option",{value:"",children:"(先加载项目)"}):null,i.projects.map(x=>s.jsxs("option",{value:x.id,children:[x.name," (",De(x.id),")"]},x.id))]}),s.jsx("button",{onClick:i.refreshProjects,children:"刷新"})]}),s.jsxs(Ut,{children:[s.jsx("input",{type:"text",placeholder:"新项目名",value:r,onChange:x=>m(x.target.value)}),s.jsxs("select",{"aria-label":"从 GitHub 仓库选",value:o,onChange:x=>{_(x.target.value),x.target.value&&N(x.target.value)},children:[s.jsx("option",{value:"",children:"(从 GitHub App 安装仓库里选,或手动输入)"}),i.githubRepos.map(x=>s.jsx("option",{value:x.clone_url,children:x.repo_full_name},x.clone_url))]}),s.jsx("input",{type:"text",placeholder:"repo_url(可选)",value:C,onChange:x=>N(x.target.value)}),s.jsx("button",{onClick:async()=>{await i.createProject(r,C),m(""),N(""),_("")},children:"新建项目"})]}),s.jsx("span",{className:"muted",children:i.projectMsg})]})}function Eg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState("contributor"),C=i.projects.find(N=>N.id===i.projectId);return s.jsxs(Qe,{title:"项目成员",children:[C?s.jsxs("div",{className:"muted",children:[C.name," | ",C.id," | 仓库 ",C.repo_url||"未绑定"," | 我的角色 ",C.my_role||"未知"]}):s.jsx("div",{className:"muted",children:"先选项目"}),s.jsxs(Ut,{children:[s.jsx("input",{type:"text",placeholder:"成员 user_id 或用户名",value:r,onChange:N=>m(N.target.value)}),s.jsxs("select",{"aria-label":"邀请角色",value:o,onChange:N=>_(N.target.value),children:[s.jsx("option",{value:"viewer",children:"viewer(只读)"}),s.jsx("option",{value:"contributor",children:"contributor(可建任务)"}),s.jsx("option",{value:"maintainer",children:"maintainer(可批合并)"}),s.jsx("option",{value:"owner",children:"owner(可管项目)"})]}),s.jsx("button",{onClick:async()=>{await i.inviteMember(r,o),m("")},children:"邀请成员"}),s.jsx("button",{onClick:i.refreshMembers,children:"刷新成员"})]}),i.memberError?s.jsx("div",{className:"muted",children:i.memberError}):i.members.length===0?s.jsx("div",{className:"muted",children:"先选项目"}):s.jsx(cu,{children:i.members.map(N=>{const x=(N.username||"")+(N.username?"("+String(N.user_id).slice(0,8)+")":String(N.user_id).slice(0,8));return s.jsxs("li",{children:[s.jsx("span",{className:"row-main",children:x}),s.jsx("select",{"aria-label":"成员角色",value:N.role||"viewer",onChange:w=>void i.changeMemberRole(N.user_id,w.target.value),children:Ly.map(w=>s.jsx("option",{value:w,children:w},w))})]},N.user_id)})}),s.jsx("span",{className:"muted",children:i.memberMsg})]})}function Ng(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState("");return s.jsxs(Qe,{id:"nav-env",title:s.jsxs(s.Fragment,{children:["环境 ",s.jsx("span",{className:"muted",children:"(选、建、管:当前项目的基准检出)"})]}),children:[s.jsxs(Ut,{children:[s.jsx("button",{onClick:i.refreshEnvs,children:"刷新"}),s.jsx("span",{className:"muted",children:i.envCount})]}),i.envs.length===0?s.jsx("div",{className:"muted",children:"先选项目"}):s.jsx(cu,{children:i.envs.map(x=>s.jsxs("li",{children:[s.jsxs("span",{className:"row-main",children:[x.name,"(",De(x.id),") / 分支 ",x.branch||"默认分支"," / 执行器 ",x.executor||"不限"," / 状态 ",x.status,x.status==="failed"&&x.error_text?" / 失败原因:"+x.error_text:""]}),x.status==="archived"?null:s.jsx("button",{onClick:()=>void i.archiveEnv(x.id),children:"归档"})]},x.id))}),s.jsxs(Ut,{children:[s.jsx("input",{type:"text",placeholder:"新环境名",value:r,onChange:x=>m(x.target.value)}),s.jsx("input",{type:"text",placeholder:"分支(可选,空=默认分支)",value:o,onChange:x=>_(x.target.value)}),s.jsxs("select",{"aria-label":"新环境执行器",value:C,onChange:x=>N(x.target.value),children:[s.jsx("option",{value:"",children:"执行器:不限"}),s.jsx("option",{value:"local",children:"local"}),s.jsx("option",{value:"docker",children:"docker"})]}),s.jsx("button",{onClick:async()=>{await i.createEnv(r,o,C),m(""),_("")},children:"新建环境"})]}),s.jsx("span",{className:"muted",children:i.envMsg})]})}function Cg(){const i=Mt(),[r,m]=v.useState("");return s.jsxs(Qe,{title:"仓库与环境上下文",children:[s.jsx("div",{className:"muted",children:i.envRepoLine||"先选项目"}),s.jsx("div",{className:"muted",children:i.envCount}),i.envRepoBar?s.jsxs(Ut,{children:[s.jsxs("select",{"aria-label":"补仓库",value:r,onChange:o=>m(o.target.value),children:[s.jsx("option",{value:"",children:"(从 GitHub App 安装仓库里选)"}),i.githubRepos.map(o=>s.jsx("option",{value:o.clone_url,children:o.repo_full_name},o.clone_url))]}),s.jsx("button",{onClick:()=>void i.saveEnvRepo(r),children:"保存仓库"})]}):null,s.jsx("span",{className:"muted",children:i.envRepoMsg})]})}function Ag(){const i=Mt();return s.jsxs(Qe,{id:"nav-workers",title:"Workers",children:[s.jsx(Ut,{children:s.jsx("button",{onClick:i.refreshWorkers,children:"刷新"})}),i.workersError?s.jsx("div",{className:"muted",children:i.workersError}):i.workers===null?s.jsx("div",{className:"muted",children:i.workersSummary||"未加载"}):i.workers.length===0?s.jsx("div",{className:"muted",children:"无 worker 注册"}):s.jsx(cu,{children:i.workers.map((r,m)=>{const o=r.running===void 0||r.running===null?"?":r.running,_=r.capacity===void 0||r.capacity===null?"?":r.capacity,C=kh(r),N=r.alive!==void 0&&r.alive!==null?!!r.alive:C.age!==null&&C.age<=120,x=N?" / 在线":" / 离线(占用为上次上报值)";return s.jsx("li",{className:N?"is-online":"is-offline",children:s.jsxs("span",{className:"row-main",children:[r.worker_id||r.id||"?"," / ",r.executor||""," / 占用 ",o,"/",_,x," / 最后心跳 ",C.text]})},m)})})]})}function Og(){const i=Mt();return s.jsxs(Qe,{title:"健康与配额",children:[s.jsxs(Ut,{children:[s.jsx("span",{className:"muted",children:i.healthText}),s.jsx("button",{onClick:i.refreshHealth,children:"刷新"})]}),s.jsx("div",{children:s.jsx("span",{className:"muted",children:i.quotaText})}),s.jsx("div",{className:"muted",children:i.workersSummary})]})}function Mg(){const i=Mt();return s.jsxs(Qe,{id:"nav-skills",title:"技能与 MCP",children:[s.jsx("div",{className:"muted",children:"反映宿主租户 home,容器内 home 可能不同;重载只在 schema 枚举里,当前 pin 的二进制拒绝时原样 502;OAuth 只发起登录,不代表登录完成。"}),s.jsxs(Ut,{children:[s.jsx("button",{onClick:i.refreshSkills,children:"刷新"}),s.jsx("span",{className:"muted",children:i.skillMsg})]}),s.jsx("h3",{children:"技能"}),i.skillError?s.jsx("div",{className:"muted",children:i.skillError}):s.jsx(Ml,{empty:"暂无技能",items:i.skills.map((r,m)=>s.jsxs("span",{className:"row-main",children:[r.name||r.id||"",r.description?" - "+r.description:"",r.detail?" - "+r.detail:""]},m))}),s.jsx("h3",{children:"应用"}),s.jsx(Ml,{empty:"暂无应用",items:i.apps.map((r,m)=>s.jsxs("span",{className:"row-main",children:[r.name||r.id||"",r.description?" - "+r.description:""]},m))}),s.jsx("h3",{children:"MCP 服务"}),s.jsx(Ml,{empty:"暂无 MCP 服务",items:i.mcpServers.map((r,m)=>{const o=r.detail||r.details||r.state||"";return s.jsxs("span",{className:"row-main",children:[r.name||r.id||""," | 状态 ",r.status||"",o?" | "+o:""]},m)})})]})}function zg(){const i=Mt(),[r,m]=v.useState("");return s.jsxs(Qe,{title:"MCP 操作",children:[s.jsxs(Ut,{children:[s.jsx("button",{onClick:i.reloadMcp,children:"重载配置"}),s.jsx("span",{className:"muted",children:i.mcpMsg})]}),s.jsxs(Ut,{children:[s.jsx("input",{type:"text",placeholder:"MCP 服务名",value:r,onChange:o=>m(o.target.value)}),s.jsx("button",{onClick:()=>void i.mcpOauth(r),children:"发起 OAuth 登录"}),s.jsx("span",{className:"muted",children:i.mcpOauthMsg})]}),i.mcpOauthBox?s.jsx("pre",{children:i.mcpOauthBox}):null]})}function Rg(){const i=Mt(),[r,m]=v.useState(""),[o,_]=v.useState(""),[C,N]=v.useState(""),[x,w]=v.useState("");return s.jsxs(s.Fragment,{children:[s.jsx("input",{placeholder:"自动化名称(同项目内启用中的名称唯一)",style:{width:"100%"},value:r,onChange:U=>m(U.target.value)}),s.jsx("textarea",{placeholder:"定时任务内容(创建只登记定义与到期状态;执行由后续执行器经 claim 抢单后建任务,不另起调度器)",value:o,onChange:U=>_(U.target.value)}),s.jsxs(Ut,{children:[s.jsx("input",{placeholder:"间隔秒数(默认 86400,最小 60)",style:{width:"40%"},value:C,onChange:U=>N(U.target.value)}),s.jsx("input",{placeholder:"仓库(可选)",style:{width:"40%"},value:x,onChange:U=>w(U.target.value)}),s.jsx("button",{className:"primary",onClick:async()=>{await i.createAutomation(r,o,C,x),m(""),_(""),N(""),w("")},children:"创建自动化"}),s.jsx("button",{onClick:i.refreshAutomations,children:"刷新自动化"}),s.jsx("span",{className:"muted",children:i.autoMsg})]}),s.jsx(Ml,{empty:"(暂无自动化)",items:i.automations.map(U=>s.jsxs("span",{className:"row-main",children:["[",U.status,U.due?"|到期":"","] ",U.name,"|每 ",U.interval_seconds," 秒|下次 ",Ga(U.next_run_at),U.status==="active"?s.jsxs(s.Fragment,{children:[" ",s.jsx("button",{onClick:()=>i.cancelAutomation(U.id),children:"取消"})]}):null]},U.id))})]})}function Dg(){var m,o,_,C;const i=Mt(),r=i.triage;return i.triageError?s.jsx("div",{className:"muted",children:i.triageError}):r?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["到期自动化(",((m=r.counts)==null?void 0:m.automations_due)||0,")"]}),s.jsx(Ml,{empty:"(无)",items:(r.automations_due||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[N.name,"|每 ",N.interval_seconds," 秒"]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["失败/中断任务(",((o=r.counts)==null?void 0:o.failed_tasks)||0,")"]}),s.jsx(Ml,{empty:"(无)",items:(r.failed_tasks||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[De(N.id),"|",N.status,"|",String(N.prompt||"").slice(0,80)]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["待处理后续消息(",((_=r.counts)==null?void 0:_.pending_followups)||0,")"]}),s.jsx(Ml,{empty:"(无)",items:(r.pending_followups||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:["任务 ",De(N.task_id),"|",String(N.body||"").slice(0,80)]},x))})]}),s.jsxs("div",{className:"data-group",children:[s.jsxs("b",{children:["最近自动化产出(",((C=r.counts)==null?void 0:C.recent_runs)||0,")"]}),s.jsx(Ml,{empty:"(无)",items:(r.recent_runs||[]).map((N,x)=>s.jsxs("span",{className:"row-main",children:[De(N.automation_id),"|",N.status,N.task_id?"|任务 "+De(N.task_id):"",N.task_status?"|"+N.task_status:""]},x))})]})]}):s.jsx("div",{className:"muted",children:"(先选项目)"})}function Ug(){return s.jsx(Qe,{id:"nav-automations",title:"自动化",children:s.jsx(Rg,{})})}function Hg(){const i=Mt();return s.jsxs(Qe,{id:"nav-triage",title:"分诊收件箱",children:[s.jsx(Ut,{children:s.jsx("button",{onClick:i.refreshTriage,children:"刷新分诊"})}),s.jsx(Dg,{})]})}const Bg=[["#sec-dispatch","派发"],["#sec-tasks","任务"],["#sec-conv","对话"],["#sec-projects","项目"],["#sec-env","环境"],["#sec-workers","Workers"],["#sec-skills","技能"],["#sec-automations","自动化"],["#sec-triage","分诊"],["#sec-admin","管理区"],["#sec-key","API Key"]];function qg(){return s.jsxs("header",{className:"dash-topbar",children:[s.jsxs("div",{className:"dash-topbar-row",children:[s.jsx("span",{className:"dash-brand",children:"Codex 命令台"}),s.jsx(Yg,{}),s.jsx("span",{className:"muted dash-hide-sm",children:s.jsx(wg,{})}),s.jsx("span",{className:"muted dash-hide-sm",children:s.jsx(Gg,{})}),s.jsx("span",{className:"muted dash-stamp",children:s.jsx(kg,{})})]}),s.jsx("nav",{className:"dash-nav","aria-label":"页面导航",children:Bg.map(([i,r])=>s.jsx("a",{href:i,children:r},i))})]})}function Yg(){const i=Mt();return s.jsx("span",{className:i.keySaved?"dash-status ok":"dash-status off",children:i.keySaved?"● 已连接":"○ 未连接"})}function wg(){return s.jsx(s.Fragment,{children:Mt().healthText})}function Gg(){return s.jsx(s.Fragment,{children:Mt().quotaText})}function kg(){return s.jsxs(s.Fragment,{children:["自动刷新 · 每 10 秒 · 已刷新 ",Mt().refreshStamp]})}function Qg(){const i=ag();tg(m=>i.refreshAll(m),1e4),eg(()=>i.refreshSlow(),6e4);const r=()=>{var m;(m=document.getElementById("sec-dispatch"))==null||m.scrollIntoView({behavior:"smooth"})};return s.jsxs(Gh.Provider,{value:i,children:[s.jsx(qg,{}),s.jsxs("main",{className:"dash-page",children:[s.jsx(ng,{}),s.jsxs("div",{className:"dash-col dash-col-left",children:[s.jsxs("section",{id:"sec-tasks",className:"dash-section card",children:[s.jsx("h2",{children:"任务列表"}),s.jsx(cg,{onNew:r})]}),s.jsxs("section",{id:"sec-projects",className:"dash-section",children:[s.jsx(_g,{}),s.jsx(Eg,{})]})]}),s.jsxs("div",{className:"dash-col dash-col-mid",children:[s.jsx("section",{id:"sec-dispatch",className:"dash-section",children:s.jsx(ug,{})}),s.jsxs("section",{id:"sec-conv",className:"dash-section",children:[s.jsxs("div",{className:"card",children:[s.jsx("h2",{children:"对话"}),s.jsx(mg,{})]}),s.jsx(xg,{})]})]}),s.jsxs("div",{className:"dash-col dash-col-right",children:[s.jsxs("section",{id:"sec-env",className:"dash-section",children:[s.jsx(Ng,{}),s.jsx(Cg,{})]}),s.jsxs("section",{id:"sec-workers",className:"dash-section",children:[s.jsx(Ag,{}),s.jsx(Og,{})]}),s.jsxs("section",{id:"sec-skills",className:"dash-section",children:[s.jsx(Mg,{}),s.jsx(zg,{})]}),s.jsx("section",{id:"sec-automations",className:"dash-section",children:s.jsx(Ug,{})}),s.jsx("section",{id:"sec-triage",className:"dash-section",children:s.jsx(Hg,{})}),s.jsx("section",{id:"sec-admin",className:"dash-section",children:s.jsx(Tg,{})}),s.jsx("section",{id:"sec-key",className:"dash-section",children:s.jsx(jg,{})})]})]})]})}Qy.createRoot(document.getElementById("root")).render(s.jsx(Uy.StrictMode,{children:s.jsx(Qg,{})}));