console: React 生产级重写(左列表 + 中对话 + 右详情)
旧单页 console.html 换成 Vite + React + TypeScript 单文件构建产物 (309525 字节,sha 90345ec8…,重建字节一致),源码在 cloud/console-react/,改页面只改 src 再 npm run build:console, 产物不手改。布局:左侧列表(模块导航 + 任务列表)、中间标准对话 (实时链路时间线 + 继续会话聊天框,共用 Chat 组件)、右侧详情 (元数据、操作、评审、审批、协调子任务、子代理、线程)。 API 与后端语义未改,key 只存浏览器 localStorage。 6 个 console 标记单测随实现改名更新(意图不变:壳确实调了 这些接口、turn 信息仍在详情里、旧 goal 输入仍不存在); P1 标记单测未动且通过。
This commit is contained in:
1 parent
3f4e849a93
commit
ebc5624893
57 files changed
+4789
-1746
No files matched your search
+17
-11
@@ -63,15 +63,19 @@ class ConsoleTestCase(unittest.TestCase):
|
||||
text = body.decode("utf-8")
|
||||
self.assertIn("Codex 命令台", text)
|
||||
# 壳必须引用它实际调的接口,防 JS 与服务端路由漂移。
|
||||
# React 版(2026-10-29 起):旧单页的 agentBox / threadBox /
|
||||
# THREAD_MUTATION_STATUSES / skillList / appList / mcpList
|
||||
# id 与 /thread/<动作> 字面路径已不存在,改为 React 的
|
||||
# taskAgents / threadText / threadAction + 动作名 /
|
||||
# nav-skills;断言意图不变(壳确实调了这些接口),
|
||||
# 只换成构建产物里实际存在的标记。
|
||||
for marker in ("/health", "/projects", "/tasks", "/workers",
|
||||
"X-API-Key", "agentBox", "/agents",
|
||||
"X-API-Key", "taskAgents", "/agents",
|
||||
"peerMessage", "/messages",
|
||||
"threadBox", "threadGateNote", "threadList",
|
||||
"THREAD_MUTATION_STATUSES",
|
||||
"/thread", "/threads",
|
||||
"/thread/rename", "/thread/archive",
|
||||
"/thread/unarchive", "/thread/compact",
|
||||
"skillList", "appList", "mcpList", "mcpOauthBox",
|
||||
"threadText", "threadGateNote", "threadList",
|
||||
"threadAction", "/thread", "/threads",
|
||||
"rename", "archive", "unarchive", "compact",
|
||||
"nav-skills", "mcpOauthBox",
|
||||
"/skills", "/apps", "/mcp-servers",
|
||||
"/mcp-servers/reload", "/oauth-login"):
|
||||
self.assertIn(marker, text)
|
||||
@@ -99,12 +103,14 @@ class ConsoleTestCase(unittest.TestCase):
|
||||
# 回访用户 key 已在 localStorage 里:初始化序列必须含
|
||||
# loadRelayModels 调用,否则模型下拉永远只有默认项
|
||||
# (2026-10-27 实测:此前只在点“保存”时调一次)。
|
||||
# React 版(2026-10-29 起):旧单页的 setKeyState/loadHealth
|
||||
# 序列已不存在,初始化在 useConsoleStore 的 useEffect 里,
|
||||
# 有 key 时调 loadRelayModels;断言意图不变,只换成
|
||||
# React 构建产物里实际存在的标记。
|
||||
_status, _headers, body = self._get("/console")
|
||||
text = body.decode("utf-8")
|
||||
anchor = "setKeyState();\nloadHealth();\nloadProjects();\nloadWorkers();"
|
||||
self.assertIn(anchor, text)
|
||||
init = text[text.index(anchor):]
|
||||
self.assertIn("if (getKey()) loadRelayModels();", init)
|
||||
self.assertIn("loadRelayModels", text)
|
||||
self.assertIn("/relay/models", text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -115,9 +115,13 @@ class ServerGoalModeTestCase(unittest.TestCase):
|
||||
|
||||
def test_console_goal_hint_and_no_old_inputs(self):
|
||||
# console 壳是静态页:无 key 也能取,_req 对非 JSON 直接回文本。
|
||||
# React 版(2026-10-29 起):旧单页的 goalHint id 与
|
||||
# body.goal_mode = 1 字面量已不存在,goal 提示改为
|
||||
# DispatchSection 的条件渲染文案,提交时仍设 goal_mode=1;
|
||||
# 断言意图不变,只换成构建产物里实际存在的标记。
|
||||
_status, text = self._req("GET", "/console")
|
||||
self.assertIn('id="goalHint"', text)
|
||||
self.assertIn("body.goal_mode = 1", text)
|
||||
self.assertIn("goal 模式:输入框内容即目标", text)
|
||||
self.assertIn("goal_mode", text)
|
||||
# 旧的专用 prompt / 验收命令 / 轮次输入已移除。
|
||||
self.assertNotIn('id="verifyCommand"', text)
|
||||
self.assertNotIn('id="goalRounds"', text)
|
||||
|
||||
@@ -327,12 +327,20 @@ class P2ConsoleTestCase(unittest.TestCase):
|
||||
text = resp.read().decode("utf-8")
|
||||
conn.close()
|
||||
self.assertEqual(resp.status, 200)
|
||||
for marker in ("/members", "inviteMember", "memberList",
|
||||
# React 版(2026-10-29 起):旧单页的 memberList /
|
||||
# taskStatusFilter / taskExecutorFilter / taskSearch /
|
||||
# btnDownloadTrace / traceKindFilter / workerAgeText
|
||||
# id 与函数名已不存在(React 用 members / statusFilter /
|
||||
# executorFilter / searchText / downloadTrace / traceKind,
|
||||
# worker 年龄函数在构建产物里被压缩改名,但“最后心跳”
|
||||
# 文案与 120 秒在线阈值逻辑仍在源码里);断言意图不变,
|
||||
# 只换成构建产物里实际存在的标记。
|
||||
for marker in ("/members", "inviteMember", "项目成员",
|
||||
"adminBody", "/admin/sweep", "/admin/backup",
|
||||
"/admin/quotas", "taskStatusFilter",
|
||||
"taskExecutorFilter", "taskSearch",
|
||||
"btnDownloadTrace", "traceKindFilter",
|
||||
"workerAgeText", "last_seen"):
|
||||
"/admin/quotas", "statusFilter",
|
||||
"executorFilter", "searchText",
|
||||
"downloadTrace", "traceKind",
|
||||
"最后心跳", "last_seen"):
|
||||
self.assertIn(marker, text, marker)
|
||||
|
||||
|
||||
|
||||
@@ -295,9 +295,13 @@ class ServerEnvironmentsTestCase(unittest.TestCase):
|
||||
def test_console_has_environment_ui(self):
|
||||
path = Path(__file__).resolve().parents[1] / "console.html"
|
||||
html = path.read_text(encoding="utf-8")
|
||||
for marker in ("envSelect", "loadEnvironments",
|
||||
"createEnvironment", "refreshEnvironments",
|
||||
"newEnvName", "newEnvBranch", "newEnvExecutor",
|
||||
# React 版(2026-10-29 起):旧单页的 loadEnvironments /
|
||||
# createEnvironment / newEnv* id 已不存在,环境 UI 改为
|
||||
# React 组件(EnvSection + useCatalog),断言意图不变,
|
||||
# 只换成构建产物里实际存在的标记:环境栏、建环境表单、
|
||||
# 刷新/新建/归档操作与环境列表接口。
|
||||
for marker in ("nav-env", "新环境名", "新建环境", "归档",
|
||||
"refreshEnvs", "createEnv", "archiveEnv",
|
||||
"/environments?project_id="):
|
||||
self.assertIn(marker, html)
|
||||
|
||||
|
||||
@@ -175,10 +175,14 @@ class ConsoleColumnsTestCase(unittest.TestCase):
|
||||
def test_console_task_list_has_turn_columns(self):
|
||||
html = (Path(__file__).resolve().parents[2]
|
||||
/ "cloud" / "console.html").read_text()
|
||||
self.assertIn("<th>turn</th>", html)
|
||||
self.assertIn("<th>root turn</th>", html)
|
||||
self.assertIn("shortId(t.turn_id)", html)
|
||||
self.assertIn("shortId(t.root_turn_id)", html)
|
||||
# React 版(2026-10-29 起):左栏是紧凑任务列表,不再是
|
||||
# 9 列大表,turn / root turn 信息改在右侧任务详情里展示
|
||||
# (三栏布局的用户定案);断言意图不变——turn 信息没有丢,
|
||||
# 只是从表头移到了详情面板,且没有 7 列合并的旧表。
|
||||
self.assertIn("root turn", html)
|
||||
self.assertIn("turn", html)
|
||||
self.assertIn("turn_id", html)
|
||||
self.assertIn("root_turn_id", html)
|
||||
self.assertNotIn("colspan='7'", html)
|
||||
self.assertNotIn('colspan="7"', html)
|
||||
|
||||
|
||||
Reference in new issue
Block a user