un2266 Claude Sonnet 5 commited on
Commit
343eabe
·
1 Parent(s): 0178c3b

Phase 4:Bug3主體——步驟列補上「失敗」視覺狀態

Browse files

- make_initial_state 新增 failed_step 欄位(1-based,成功時維持 None)
- _build_header_html 新增 failed_step 參數,該步驟改用紅色警示樣式,
不再套用「進行中」的呼吸動畫(原本失敗時圓點會永遠卡在動畫)
- run_computation_pipeline_streaming 的指標計算/統計分析例外分支
分別標記 failed_step=5/6,錯誤訊息補上「請重新整理頁面重新開始」
的下一步指引(完整的重置機制留給 Phase 6 一併處理)
- 新增 .step-pill--failed CSS 樣式

已用直接呼叫 _build_header_html(failed_step=5) 驗證渲染邏輯正確;
Phase 3 的驗證強化讓最容易觸發此失敗路徑的成因(分組不完整)已被攔在
格式驗證階段,因此另外完整跑一次情境1 happy path 確認沒有回歸。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Files changed (1) hide show
  1. app_agent.py +29 -4
app_agent.py CHANGED
@@ -1370,6 +1370,7 @@ def make_initial_state(session_id: str) -> dict:
1370
  "analysis_result": None,
1371
  "done_steps": [], # 已完成步驟(1-based)
1372
  "current_step": None, # 目前執行步驟
 
1373
  }
1374
 
1375
 
@@ -1386,18 +1387,27 @@ _STEPS = [
1386
  ]
1387
 
1388
 
1389
- def _build_header_html(done_steps: list = None, current_step: int = None) -> str:
 
1390
  """
1391
  產生完整標題區塊 HTML(標題+動態步驟列+進度條),確定性、不依賴 LLM。
1392
  取代原本寫死不會變的步驟列,以及原本另外放在右欄、跟這裡資訊重複的
1393
  「執行進度」面板——進度資訊現在只在這裡出現一次。
1394
  done_steps: 已完成步驟(1-based list)
1395
  current_step: 目前執行步驟(1-based int)
 
 
 
1396
  """
1397
  done_steps = done_steps or []
1398
  pills = []
1399
  for num, name in _STEPS:
1400
- if num in done_steps:
 
 
 
 
 
1401
  pills.append(
1402
  f'<span class="step-pill step-pill--done">'
1403
  f'<span class="step-num">✓</span>{name}</span>'
@@ -1588,7 +1598,8 @@ def run_computation_pipeline_streaming(state: dict):
1588
  yield f" [OK] 指標計算完成({len(idx_df)} 個文本)", False, state
1589
  except Exception as e:
1590
  state["state"] = "COMPLETE"
1591
- yield f"[ERROR] 指標計算失敗:{e}", True, state
 
1592
  return
1593
 
1594
  # ── 步驟 2:統計分析 ─────────────────────────────────────────────────────
@@ -1612,7 +1623,8 @@ def run_computation_pipeline_streaming(state: dict):
1612
  except Exception as e:
1613
  state["state"] = "COMPLETE"
1614
  state["output_files"] = results_paths
1615
- yield f"[ERROR] 統計分析失敗:{e}", True, state
 
1616
  return
1617
 
1618
  # ── 步驟 3:LLM 研究報告 ────────────────────────────────────────────────
@@ -1935,6 +1947,18 @@ _CUSTOM_CSS = """
1935
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--c-accent-rgb),.35); }
1936
  50% { box-shadow: 0 0 0 5px rgba(var(--c-accent-rgb),0); }
1937
  }
 
 
 
 
 
 
 
 
 
 
 
 
1938
  /* 步驟列下方的整體進度條,取代原本另外放在右欄、跟步驟列資訊重複的執行進度面板 */
1939
  .step-progress-track {
1940
  height: 4px;
@@ -3159,6 +3183,7 @@ def create_app():
3159
  value=_build_header_html(
3160
  state.get("done_steps", []),
3161
  state.get("current_step"),
 
3162
  )
3163
  )
3164
 
 
1370
  "analysis_result": None,
1371
  "done_steps": [], # 已完成步驟(1-based)
1372
  "current_step": None, # 目前執行步驟
1373
+ "failed_step": None, # 執行失敗時卡在哪一步(1-based),成功時維持 None
1374
  }
1375
 
1376
 
 
1387
  ]
1388
 
1389
 
1390
+ def _build_header_html(done_steps: list = None, current_step: int = None,
1391
+ failed_step: int = None) -> str:
1392
  """
1393
  產生完整標題區塊 HTML(標題+動態步驟列+進度條),確定性、不依賴 LLM。
1394
  取代原本寫死不會變的步驟列,以及原本另外放在右欄、跟這裡資訊重複的
1395
  「執行進度」面板——進度資訊現在只在這裡出現一次。
1396
  done_steps: 已完成步驟(1-based list)
1397
  current_step: 目前執行步驟(1-based int)
1398
+ failed_step: 執行失敗時卡住的步驟(1-based int),失敗時該步驟改用失敗樣式,
1399
+ 不再顯示「進行中」的呼吸動畫(原本失敗時圓點會永遠卡在動畫,
1400
+ 使用者容易誤以為系統還在運算而手滑刷新頁面)
1401
  """
1402
  done_steps = done_steps or []
1403
  pills = []
1404
  for num, name in _STEPS:
1405
+ if num == failed_step:
1406
+ pills.append(
1407
+ f'<span class="step-pill step-pill--failed">'
1408
+ f'<span class="step-num">!</span>{name}</span>'
1409
+ )
1410
+ elif num in done_steps:
1411
  pills.append(
1412
  f'<span class="step-pill step-pill--done">'
1413
  f'<span class="step-num">✓</span>{name}</span>'
 
1598
  yield f" [OK] 指標計算完成({len(idx_df)} 個文本)", False, state
1599
  except Exception as e:
1600
  state["state"] = "COMPLETE"
1601
+ state["failed_step"] = 5
1602
+ yield f"[ERROR] 指標計算失敗:{e}\n\n請重新整理頁面,重新開始分析。", True, state
1603
  return
1604
 
1605
  # ── 步驟 2:統計分析 ─────────────────────────────────────────────────────
 
1623
  except Exception as e:
1624
  state["state"] = "COMPLETE"
1625
  state["output_files"] = results_paths
1626
+ state["failed_step"] = 6
1627
+ yield f"[ERROR] 統計分析失敗:{e}\n\n請重新整理頁面,重新開始分析。", True, state
1628
  return
1629
 
1630
  # ── 步驟 3:LLM 研究報告 ────────────────────────────────────────────────
 
1947
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--c-accent-rgb),.35); }
1948
  50% { box-shadow: 0 0 0 5px rgba(var(--c-accent-rgb),0); }
1949
  }
1950
+ /* 執行失敗卡住的步驟:紅色警示樣式,且不套用 stepPulse 呼吸動畫——原本
1951
+ 失敗時圓點會卡在「進行中」動畫永遠閃爍,讓使用者誤以為系統還在運算 */
1952
+ .step-pill--failed {
1953
+ background: rgba(220,38,38,.14);
1954
+ border-color: rgba(220,38,38,.4);
1955
+ color: #dc2626;
1956
+ font-weight: 700;
1957
+ }
1958
+ .step-pill--failed .step-num {
1959
+ background: #dc2626;
1960
+ color: #fff;
1961
+ }
1962
  /* 步驟列下方的整體進度條,取代原本另外放在右欄、跟步驟列資訊重複的執行進度面板 */
1963
  .step-progress-track {
1964
  height: 4px;
 
3183
  value=_build_header_html(
3184
  state.get("done_steps", []),
3185
  state.get("current_step"),
3186
+ state.get("failed_step"),
3187
  )
3188
  )
3189