Deploy SmartPaper R3-Free UI State Fix

#7
Files changed (1) hide show
  1. managed_auth.py +40 -5
managed_auth.py CHANGED
@@ -29,6 +29,34 @@ from smartpaper_restore_bridge import edge_bridge
29
  EDGE_ASSERTION_COOKIE_NAME = "smartpaper_edge_assertion"
30
  EDGE_ASSERTION_AUDIENCE = "smartpaper-streamlit"
31
  ASSERTION_CLOCK_SKEW_SECONDS = 30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  def _runtime_value(name: str) -> str:
33
  value = os.environ.get(name, "")
34
  if not value:
@@ -129,7 +157,7 @@ def _verify_edge_assertion(token: str) -> dict[str, Any]:
129
 
130
  def _clear_generation_session_state() -> None:
131
  for key in (
132
- "sp_generation_task", "sp_current_node",
133
  "sp_generation_idempotency_key", "zip_buffer", "zip_filename",
134
  "is_running", "start_pipeline", "resume_pipeline", "run_mode",
135
  "rag_engine", "up_amj_ref", "up_amj_data", "up_asq_ref",
@@ -241,10 +269,12 @@ def get_account_snapshot(*, block: bool = False) -> dict[str, Any] | None:
241
  st.session_state["sp_user"] = dict(user)
242
  task = result.get("task")
243
  latest_task = result.get("latest_task")
244
- if isinstance(task, dict) and task.get("task_id"):
245
- st.session_state["sp_generation_task"] = dict(task)
246
- elif isinstance(latest_task, dict) and latest_task.get("task_id"):
247
- st.session_state["sp_generation_task"] = dict(latest_task)
 
 
248
  else:
249
  st.session_state["sp_generation_task"] = None
250
  return result
@@ -270,6 +300,9 @@ def start_generation_task(*, idempotency_key: str, mode: str, interface_language
270
  if not result.get("ok"):
271
  _raise_edge_error(result, "task_start_failed")
272
  _merge_quota_into_session(result)
 
 
 
273
  return dict(result)
274
 
275
 
@@ -297,6 +330,8 @@ def generation_task_status(task_id: str) -> dict[str, Any]:
297
  task = result.get("task")
298
  if isinstance(task, dict):
299
  st.session_state["sp_generation_task"] = dict(task)
 
 
300
  return dict(result)
301
 
302
 
 
29
  EDGE_ASSERTION_COOKIE_NAME = "smartpaper_edge_assertion"
30
  EDGE_ASSERTION_AUDIENCE = "smartpaper-streamlit"
31
  ASSERTION_CLOCK_SKEW_SECONDS = 30
32
+ ACTIVE_GENERATION_STATUSES = frozenset({"created", "running", "resumable", "cancelling"})
33
+ KNOWN_GENERATION_STATUSES = ACTIVE_GENERATION_STATUSES | frozenset({"completed", "failed", "cancelled"})
34
+
35
+
36
+ def _select_generation_task_for_session(
37
+ active_task: Any, latest_task: Any, tracked_task_id: str
38
+ ) -> dict[str, Any] | None:
39
+ """Choose only a genuinely current task for the Streamlit session.
40
+
41
+ ``latest_task`` is historical data. It may update the terminal state of a
42
+ task that this Streamlit session already tracked, but it must never create a
43
+ current-task UI state on a fresh login/session by itself.
44
+ """
45
+ if isinstance(active_task, dict) and active_task.get("task_id"):
46
+ status = str(active_task.get("status") or "").strip().lower()
47
+ if status in ACTIVE_GENERATION_STATUSES:
48
+ return dict(active_task)
49
+
50
+ tracked = str(tracked_task_id or "").strip()
51
+ if not tracked or not isinstance(latest_task, dict):
52
+ return None
53
+ latest_id = str(latest_task.get("task_id") or "").strip()
54
+ latest_status = str(latest_task.get("status") or "").strip().lower()
55
+ if latest_id == tracked and latest_status in KNOWN_GENERATION_STATUSES:
56
+ return dict(latest_task)
57
+ return None
58
+
59
+
60
  def _runtime_value(name: str) -> str:
61
  value = os.environ.get(name, "")
62
  if not value:
 
157
 
158
  def _clear_generation_session_state() -> None:
159
  for key in (
160
+ "sp_generation_task", "sp_tracked_task_id", "sp_current_node",
161
  "sp_generation_idempotency_key", "zip_buffer", "zip_filename",
162
  "is_running", "start_pipeline", "resume_pipeline", "run_mode",
163
  "rag_engine", "up_amj_ref", "up_amj_data", "up_asq_ref",
 
269
  st.session_state["sp_user"] = dict(user)
270
  task = result.get("task")
271
  latest_task = result.get("latest_task")
272
+ selected_task = _select_generation_task_for_session(
273
+ task, latest_task, str(st.session_state.get("sp_tracked_task_id") or "")
274
+ )
275
+ if selected_task is not None:
276
+ st.session_state["sp_generation_task"] = selected_task
277
+ st.session_state["sp_tracked_task_id"] = str(selected_task.get("task_id") or "")
278
  else:
279
  st.session_state["sp_generation_task"] = None
280
  return result
 
300
  if not result.get("ok"):
301
  _raise_edge_error(result, "task_start_failed")
302
  _merge_quota_into_session(result)
303
+ started_task = result.get("task")
304
+ if isinstance(started_task, dict) and started_task.get("task_id"):
305
+ st.session_state["sp_tracked_task_id"] = str(started_task["task_id"])
306
  return dict(result)
307
 
308
 
 
330
  task = result.get("task")
331
  if isinstance(task, dict):
332
  st.session_state["sp_generation_task"] = dict(task)
333
+ if task.get("task_id"):
334
+ st.session_state["sp_tracked_task_id"] = str(task["task_id"])
335
  return dict(result)
336
 
337