feat(v3): Web 应用化基线(异步任务/SSE/llama-server 管理/Vue SPA 四页 + 设置页整页滚动修复)

This commit is contained in:
tzt
2026-09-01 08:31:47 +08:00
parent 8d36eeec59
commit 3bbdcb7cc7
60 changed files with 7236 additions and 1160 deletions
+20 -3
View File
@@ -68,8 +68,9 @@ class CollaborativePipeline:
# ---------------------------------------------------------------
# 入口
# ---------------------------------------------------------------
async def run(self, query: str) -> PipelineResult:
request_id = uuid.uuid4().hex[:12]
async def run(self, query: str, request_id: Optional[str] = None) -> PipelineResult:
if request_id is None:
request_id = uuid.uuid4().hex[:12]
ws = Workspace.new(request_id, query, self.api_token_cap, self.rounds_cap)
route: List[str] = ["v2"]
t0 = time.perf_counter() * 1000.0
@@ -100,11 +101,15 @@ class CollaborativePipeline:
route.append("loop")
plan = brief.get("plan") or []
pending = [p.get("id") for p in plan]
plan_ids = {p.get("id") for p in plan} # 用于 _deps_done 过滤
while pending and not ws.exhausted():
progressed = False
for sid in list(pending):
step = next((p for p in plan if p.get("id") == sid), {})
if not self._deps_done(ws, step.get("deps") or []):
deps = step.get("deps") or []
# 只检查在 plan 中的依赖;不在 plan 的 ID 视为"不存在"→自动满足
relevant = [d for d in deps if d in plan_ids]
if not self._deps_done(ws, relevant):
continue
existing = self._read_artifact(request_id, self._artifact_name(sid, ws))
outcome = await self.worker.run_step(ws, sid, existing_artifact=existing,
@@ -115,6 +120,8 @@ class CollaborativePipeline:
ws.rollup()
route.append(f"step:{sid}:done")
progressed = True
if not pending: # 所有步骤完成,退出循环
break
else: # issue -> Architect 裁决
route.append(f"step:{sid}:issue")
try:
@@ -227,7 +234,17 @@ class CollaborativePipeline:
return artifact_name_for(sid, domain)
def _deps_done(self, ws: Workspace, deps: List[str]) -> bool:
# progress 中 done 的条目;done 条目 rollup 后移到 archive(字符串格式如 "s1: ..."
done = {p["step"] for p in ws.get("progress", []) if p.get("status") == "done"}
for entry in ws.get("archive", []):
if isinstance(entry, dict):
sid = entry.get("step", "")
elif isinstance(entry, str):
sid = entry.split(":")[0].strip() if ":" in entry else ""
else:
sid = ""
if sid in deps:
done.add(sid)
return all(d in done for d in deps)
def _last_decision_for(self, ws: Workspace, sid: str) -> str: