Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Deploy v4.6.20 agent reliability fixes
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- README.md +1 -1
- VERSION +1 -1
- codex_harness.py +18 -6
- codex_native_harness.py +37 -1
- services/chat_runtime.py +113 -43
- static/js/app.js +1 -1
- tests/test_agent_reliability_v4620.py +51 -0
- tests/test_api_entry_preflight_v456.py +1 -1
- tests/test_chat_lifecycle_progress_v393.py +1 -1
- tests/test_clarification_ui_v454.py +1 -1
- tests/test_classification_cleanup_v466.py +1 -1
- tests/test_context_and_multitask_finalize_v451.py +1 -1
- tests/test_conversation_summary_v4613.py +1 -1
- tests/test_download_host_authorization_v460.py +1 -1
- tests/test_download_opfs_fallback_v459.py +1 -1
- tests/test_download_overlay_v4618.py +1 -1
- tests/test_download_progress_v391.py +1 -1
- tests/test_download_resilience_v422.py +1 -1
- tests/test_frontend_preflight_v457.py +1 -1
- tests/test_history_dedupe_recent_summary_v4614.py +1 -1
- tests/test_history_sidebar_v373.py +1 -1
- tests/test_large_download_jobs_v400.py +1 -1
- tests/test_manual_tasks_v469.py +2 -2
- tests/test_merged_health_v433.py +1 -1
- tests/test_multitask_observability_v442.py +1 -1
- tests/test_multitask_sse_finalize_v452.py +1 -1
- tests/test_noaa_ramldb_roles_v465.py +1 -1
- tests/test_ocean_batch_downloads_v420.py +3 -3
- tests/test_ocean_batch_routing_v421.py +1 -1
- tests/test_ocean_batch_v410.py +1 -1
- tests/test_ocean_batch_zip_manifest_v4619.py +1 -1
- tests/test_ocean_date_default_v453.py +1 -1
- tests/test_ocean_download_url_base_v462.py +1 -1
- tests/test_p0_finish_v380.py +1 -1
- tests/test_p0_phase2_v371.py +1 -1
- tests/test_p0_phase3_v372.py +1 -1
- tests/test_platform_reliability_v450.py +2 -2
- tests/test_product_finish_v4615.py +1 -1
- tests/test_project_package_download_v4617.py +2 -2
- tests/test_quality_center_v362.py +1 -1
- tests/test_quality_trust_v361.py +1 -1
- tests/test_reference_cleanup_v468.py +1 -1
- tests/test_release_stability.py +1 -1
- tests/test_resumable_batch_download_v458.py +1 -1
- tests/test_route_region_clarification_v455.py +1 -1
- tests/test_runtime_hotfix_v376.py +1 -1
- tests/test_sidebar_collapse_v374.py +1 -1
- tests/test_sidebar_partial_collapse_v375.py +1 -1
- tests/test_smart_progress_avatar_sync_v441.py +1 -1
- tests/test_source_mapping_roles_v464.py +1 -1
README.md
CHANGED
|
@@ -10,7 +10,7 @@ pinned: false
|
|
| 10 |
|
| 11 |
# Global Marine Foundation Data Agent
|
| 12 |
|
| 13 |
-
Current UI release: **v4.6.
|
| 14 |
|
| 15 |
|
| 16 |
## v3.4.0 稳定性重构(第一阶段)
|
|
|
|
| 10 |
|
| 11 |
# Global Marine Foundation Data Agent
|
| 12 |
|
| 13 |
+
Current UI release: **v4.6.20**.
|
| 14 |
|
| 15 |
|
| 16 |
## v3.4.0 稳定性重构(第一阶段)
|
VERSION
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
4.6.
|
|
|
|
| 1 |
+
4.6.20
|
codex_harness.py
CHANGED
|
@@ -12,6 +12,8 @@ from dataclasses import dataclass
|
|
| 12 |
class CodexResult:
|
| 13 |
final_response: str
|
| 14 |
finish_reason: str = "completed"
|
|
|
|
|
|
|
| 15 |
|
| 16 |
|
| 17 |
class CodexHarness:
|
|
@@ -171,7 +173,7 @@ class CodexHarness:
|
|
| 171 |
result = getattr(marine_mcp, short)(**args)
|
| 172 |
return CodexHarness._jsonable(result)
|
| 173 |
|
| 174 |
-
def _request(self, body: dict) -> dict:
|
| 175 |
request = urllib.request.Request(
|
| 176 |
self.base_url + "/responses",
|
| 177 |
data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
|
|
@@ -181,7 +183,7 @@ class CodexHarness:
|
|
| 181 |
"Content-Type": "application/json",
|
| 182 |
"Accept": "application/json",
|
| 183 |
"User-Agent": "Global-Marine-Foundation/4.5",
|
| 184 |
-
"x-opencode-session": str(
|
| 185 |
},
|
| 186 |
)
|
| 187 |
try:
|
|
@@ -222,7 +224,7 @@ class CodexHarness:
|
|
| 222 |
def run(self, prompt, session_id=None):
|
| 223 |
if not self.api_key:
|
| 224 |
raise RuntimeError("OPENCODE_GO_API_KEY is not configured")
|
| 225 |
-
|
| 226 |
full_prompt = (self.system_prompt + "\n\n" + prompt).strip()
|
| 227 |
tools = self._tools()
|
| 228 |
payload = self._request({
|
|
@@ -230,7 +232,9 @@ class CodexHarness:
|
|
| 230 |
"input": full_prompt,
|
| 231 |
"tools": tools,
|
| 232 |
"tool_choice": "auto",
|
| 233 |
-
})
|
|
|
|
|
|
|
| 234 |
|
| 235 |
# Responses can contain multiple tool calls. Execute them locally,
|
| 236 |
# then continue the same Responses conversation until text is final.
|
|
@@ -240,10 +244,18 @@ class CodexHarness:
|
|
| 240 |
break
|
| 241 |
outputs = []
|
| 242 |
for call in calls:
|
|
|
|
|
|
|
| 243 |
try:
|
| 244 |
value = self._run_tool(call["name"], call["arguments"])
|
| 245 |
except Exception as exc:
|
| 246 |
value = {"status": "error", "detail": str(exc)[:1000]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
outputs.append({
|
| 248 |
"type": "function_call_output",
|
| 249 |
"call_id": call["call_id"],
|
|
@@ -256,11 +268,11 @@ class CodexHarness:
|
|
| 256 |
"tools": tools,
|
| 257 |
"tool_choice": "auto",
|
| 258 |
}
|
| 259 |
-
payload = self._request(next_body)
|
| 260 |
else:
|
| 261 |
raise RuntimeError("OpenCode Go tool loop exceeded 8 rounds")
|
| 262 |
|
| 263 |
answer = self._text(payload)
|
| 264 |
if not answer:
|
| 265 |
raise RuntimeError("OpenCode Go returned no text: " + json.dumps(payload, ensure_ascii=False)[:1200])
|
| 266 |
-
return CodexResult(final_response=answer)
|
|
|
|
| 12 |
class CodexResult:
|
| 13 |
final_response: str
|
| 14 |
finish_reason: str = "completed"
|
| 15 |
+
tool_names: tuple[str, ...] = ()
|
| 16 |
+
tool_events: tuple[str, ...] = ()
|
| 17 |
|
| 18 |
|
| 19 |
class CodexHarness:
|
|
|
|
| 173 |
result = getattr(marine_mcp, short)(**args)
|
| 174 |
return CodexHarness._jsonable(result)
|
| 175 |
|
| 176 |
+
def _request(self, body: dict, session_id: str) -> dict:
|
| 177 |
request = urllib.request.Request(
|
| 178 |
self.base_url + "/responses",
|
| 179 |
data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
|
|
|
|
| 183 |
"Content-Type": "application/json",
|
| 184 |
"Accept": "application/json",
|
| 185 |
"User-Agent": "Global-Marine-Foundation/4.5",
|
| 186 |
+
"x-opencode-session": str(session_id),
|
| 187 |
},
|
| 188 |
)
|
| 189 |
try:
|
|
|
|
| 224 |
def run(self, prompt, session_id=None):
|
| 225 |
if not self.api_key:
|
| 226 |
raise RuntimeError("OPENCODE_GO_API_KEY is not configured")
|
| 227 |
+
request_session_id = str(session_id or uuid.uuid4())
|
| 228 |
full_prompt = (self.system_prompt + "\n\n" + prompt).strip()
|
| 229 |
tools = self._tools()
|
| 230 |
payload = self._request({
|
|
|
|
| 232 |
"input": full_prompt,
|
| 233 |
"tools": tools,
|
| 234 |
"tool_choice": "auto",
|
| 235 |
+
}, request_session_id)
|
| 236 |
+
tool_names = []
|
| 237 |
+
tool_events = []
|
| 238 |
|
| 239 |
# Responses can contain multiple tool calls. Execute them locally,
|
| 240 |
# then continue the same Responses conversation until text is final.
|
|
|
|
| 244 |
break
|
| 245 |
outputs = []
|
| 246 |
for call in calls:
|
| 247 |
+
if call["name"] not in tool_names:
|
| 248 |
+
tool_names.append(call["name"])
|
| 249 |
try:
|
| 250 |
value = self._run_tool(call["name"], call["arguments"])
|
| 251 |
except Exception as exc:
|
| 252 |
value = {"status": "error", "detail": str(exc)[:1000]}
|
| 253 |
+
if len(tool_events)<40:
|
| 254 |
+
tool_events.append(json.dumps({
|
| 255 |
+
"name":call["name"],
|
| 256 |
+
"arguments":call["arguments"],
|
| 257 |
+
"result":value,
|
| 258 |
+
},ensure_ascii=False,default=str)[:12000])
|
| 259 |
outputs.append({
|
| 260 |
"type": "function_call_output",
|
| 261 |
"call_id": call["call_id"],
|
|
|
|
| 268 |
"tools": tools,
|
| 269 |
"tool_choice": "auto",
|
| 270 |
}
|
| 271 |
+
payload = self._request(next_body, request_session_id)
|
| 272 |
else:
|
| 273 |
raise RuntimeError("OpenCode Go tool loop exceeded 8 rounds")
|
| 274 |
|
| 275 |
answer = self._text(payload)
|
| 276 |
if not answer:
|
| 277 |
raise RuntimeError("OpenCode Go returned no text: " + json.dumps(payload, ensure_ascii=False)[:1200])
|
| 278 |
+
return CodexResult(final_response=answer, tool_names=tuple(tool_names), tool_events=tuple(tool_events))
|
codex_native_harness.py
CHANGED
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
| 9 |
|
| 10 |
import json
|
| 11 |
import os
|
|
|
|
| 12 |
import shutil
|
| 13 |
import subprocess
|
| 14 |
import uuid
|
|
@@ -20,6 +21,8 @@ from typing import Any
|
|
| 20 |
class CodexResult:
|
| 21 |
final_response: str
|
| 22 |
finish_reason: str = "completed"
|
|
|
|
|
|
|
| 23 |
|
| 24 |
|
| 25 |
def _text_from_value(value: Any) -> str:
|
|
@@ -52,6 +55,27 @@ def _event_text(event: dict[str, Any]) -> str:
|
|
| 52 |
return ""
|
| 53 |
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
class CodexNativeHarness:
|
| 56 |
"""Run the official Codex CLI with the configured MCP server."""
|
| 57 |
|
|
@@ -142,6 +166,8 @@ class CodexNativeHarness:
|
|
| 142 |
raise RuntimeError(f"无法启动官方 Codex CLI: {exc}") from exc
|
| 143 |
|
| 144 |
candidates: list[str] = []
|
|
|
|
|
|
|
| 145 |
for line in (completed.stdout or "").splitlines():
|
| 146 |
raw = line.strip()
|
| 147 |
if not raw:
|
|
@@ -154,6 +180,16 @@ class CodexNativeHarness:
|
|
| 154 |
text = _event_text(event)
|
| 155 |
if text:
|
| 156 |
candidates.append(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
|
| 158 |
if completed.returncode != 0:
|
| 159 |
stderr_detail = (completed.stderr or "").strip()[-1200:]
|
|
@@ -172,4 +208,4 @@ class CodexNativeHarness:
|
|
| 172 |
answer = candidates[-1].strip() if candidates else ""
|
| 173 |
if not answer:
|
| 174 |
raise RuntimeError("官方 Codex CLI 没有返回最终文本")
|
| 175 |
-
return CodexResult(final_response=answer)
|
|
|
|
| 9 |
|
| 10 |
import json
|
| 11 |
import os
|
| 12 |
+
import re
|
| 13 |
import shutil
|
| 14 |
import subprocess
|
| 15 |
import uuid
|
|
|
|
| 21 |
class CodexResult:
|
| 22 |
final_response: str
|
| 23 |
finish_reason: str = "completed"
|
| 24 |
+
tool_names: tuple[str, ...] = ()
|
| 25 |
+
tool_events: tuple[str, ...] = ()
|
| 26 |
|
| 27 |
|
| 28 |
def _text_from_value(value: Any) -> str:
|
|
|
|
| 55 |
return ""
|
| 56 |
|
| 57 |
|
| 58 |
+
_MARINE_TOOL_RE = re.compile(r"\bmcp_marine_[A-Za-z0-9_]+\b")
|
| 59 |
+
|
| 60 |
+
def _tool_names_from_event(event: dict[str, Any]) -> list[str]:
|
| 61 |
+
if not isinstance(event, dict):
|
| 62 |
+
return []
|
| 63 |
+
event_type=str(event.get("type") or "").lower()
|
| 64 |
+
item=event.get("item") if isinstance(event.get("item"),dict) else {}
|
| 65 |
+
item_type=str(item.get("type") or "").lower()
|
| 66 |
+
tool_shaped=(
|
| 67 |
+
any(token in event_type for token in ("tool","mcp","function"))
|
| 68 |
+
or any(token in item_type for token in ("tool","mcp","function"))
|
| 69 |
+
)
|
| 70 |
+
if not tool_shaped:
|
| 71 |
+
return []
|
| 72 |
+
try:
|
| 73 |
+
raw=json.dumps(event,ensure_ascii=False,default=str)
|
| 74 |
+
except Exception:
|
| 75 |
+
raw=str(event)
|
| 76 |
+
return list(dict.fromkeys(_MARINE_TOOL_RE.findall(raw)))
|
| 77 |
+
|
| 78 |
+
|
| 79 |
class CodexNativeHarness:
|
| 80 |
"""Run the official Codex CLI with the configured MCP server."""
|
| 81 |
|
|
|
|
| 166 |
raise RuntimeError(f"无法启动官方 Codex CLI: {exc}") from exc
|
| 167 |
|
| 168 |
candidates: list[str] = []
|
| 169 |
+
tool_names: list[str] = []
|
| 170 |
+
tool_events: list[str] = []
|
| 171 |
for line in (completed.stdout or "").splitlines():
|
| 172 |
raw = line.strip()
|
| 173 |
if not raw:
|
|
|
|
| 180 |
text = _event_text(event)
|
| 181 |
if text:
|
| 182 |
candidates.append(text)
|
| 183 |
+
names=_tool_names_from_event(event)
|
| 184 |
+
if names:
|
| 185 |
+
for name in names:
|
| 186 |
+
if name not in tool_names:
|
| 187 |
+
tool_names.append(name)
|
| 188 |
+
if len(tool_events)<40:
|
| 189 |
+
try:
|
| 190 |
+
tool_events.append(json.dumps(event,ensure_ascii=False,default=str)[:12000])
|
| 191 |
+
except Exception:
|
| 192 |
+
tool_events.append(str(event)[:12000])
|
| 193 |
|
| 194 |
if completed.returncode != 0:
|
| 195 |
stderr_detail = (completed.stderr or "").strip()[-1200:]
|
|
|
|
| 208 |
answer = candidates[-1].strip() if candidates else ""
|
| 209 |
if not answer:
|
| 210 |
raise RuntimeError("官方 Codex CLI 没有返回最终文本")
|
| 211 |
+
return CodexResult(final_response=answer, tool_names=tuple(tool_names), tool_events=tuple(tool_events))
|
services/chat_runtime.py
CHANGED
|
@@ -535,11 +535,30 @@ async def harness_stream_chat(tid,prompt):
|
|
| 535 |
tid,
|
| 536 |
USER_SYSTEM,
|
| 537 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 538 |
|
| 539 |
harness_prompt=(
|
| 540 |
"[APPLICATION_CONTEXT]\n"
|
| 541 |
+ app_context
|
| 542 |
+ "\n[/APPLICATION_CONTEXT]\n\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 543 |
+ "[CURRENT_USER_MESSAGE]\n"
|
| 544 |
+ prompt
|
| 545 |
+ "\n[/CURRENT_USER_MESSAGE]"
|
|
@@ -591,6 +610,23 @@ async def harness_stream_chat(tid,prompt):
|
|
| 591 |
"Codex Harness 没有返回有效文本。"
|
| 592 |
)
|
| 593 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 594 |
log.info(
|
| 595 |
"Codex Harness completed: "
|
| 596 |
"thread=%s model=%s reason=%s uploads=%s",
|
|
@@ -628,12 +664,11 @@ async def harness_stream_chat(tid,prompt):
|
|
| 628 |
len(pending_uploads),
|
| 629 |
)
|
| 630 |
|
|
|
|
| 631 |
yield out(
|
| 632 |
"error",
|
| 633 |
{
|
| 634 |
-
"text":
|
| 635 |
-
"Codex Harness 调用失败:"
|
| 636 |
-
+ str(exc)[:500],
|
| 637 |
"stage":"harness",
|
| 638 |
},
|
| 639 |
)
|
|
@@ -655,14 +690,23 @@ def _is_runtime_info_prompt(prompt: str) -> bool:
|
|
| 655 |
|
| 656 |
|
| 657 |
def _is_marine_health_prompt(prompt: str) -> bool:
|
| 658 |
-
"""Recognize
|
| 659 |
-
text
|
| 660 |
-
|
|
|
|
|
|
|
| 661 |
"海洋数据服务器连接", "检查海洋数据服务器", "数据服务器连接",
|
| 662 |
-
"三个
|
| 663 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
)
|
| 665 |
-
|
|
|
|
| 666 |
|
| 667 |
|
| 668 |
def _is_fisheries_inventory_prompt(prompt: str) -> bool:
|
|
@@ -795,55 +839,81 @@ async def _direct_fisheries_inventory_answer(prompt: str) -> str:
|
|
| 795 |
|
| 796 |
|
| 797 |
async def _direct_marine_health_answer():
|
| 798 |
-
"""Query
|
| 799 |
-
httpx_module
|
| 800 |
if httpx_module is None:
|
| 801 |
try:
|
| 802 |
import httpx as httpx_module
|
| 803 |
except Exception as exc:
|
| 804 |
return f"海洋数据服务器连接检查失败:HTTP 客户端不可用({exc})"
|
| 805 |
-
base
|
| 806 |
if not base:
|
| 807 |
return "海洋数据服务器未配置 MARINE_API_URL。"
|
| 808 |
|
| 809 |
-
|
| 810 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 811 |
if not base.endswith("/marine"):
|
| 812 |
-
candidates.append(f"{base}/marine/
|
| 813 |
-
|
| 814 |
-
|
| 815 |
-
async with httpx_module.AsyncClient(timeout=12.0, follow_redirects=True) as client:
|
| 816 |
for url in candidates:
|
| 817 |
try:
|
| 818 |
-
response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 819 |
if response.is_success:
|
| 820 |
-
payload = response.json()
|
| 821 |
-
domains = payload.get("domains") if isinstance(payload, dict) else None
|
| 822 |
-
labels = {
|
| 823 |
-
"ocean": "在线",
|
| 824 |
-
"tuna": "在线",
|
| 825 |
-
"squid": "在线",
|
| 826 |
-
}
|
| 827 |
-
if isinstance(domains, dict):
|
| 828 |
-
for key in labels:
|
| 829 |
-
value = domains.get(key)
|
| 830 |
-
if isinstance(value, dict):
|
| 831 |
-
value = value.get("status") or value.get("online")
|
| 832 |
-
if value in (False, "offline", "未连接", "不可用"):
|
| 833 |
-
labels[key] = "离线/不可用"
|
| 834 |
-
elif isinstance(domains, list):
|
| 835 |
-
for key in labels:
|
| 836 |
-
if key not in {str(item).lower() for item in domains}:
|
| 837 |
-
labels[key] = "未在健康响应中列出"
|
| 838 |
return (
|
| 839 |
-
"
|
| 840 |
-
|
| 841 |
-
f"- Tuna:{labels['tuna']}\n"
|
| 842 |
-
f"- Squid:{labels['squid']}"
|
| 843 |
)
|
| 844 |
-
last_error
|
| 845 |
except Exception as exc:
|
| 846 |
-
last_error
|
| 847 |
return f"海洋数据服务器连接检查失败:{last_error[:240]}"
|
| 848 |
|
| 849 |
|
|
|
|
| 535 |
tid,
|
| 536 |
USER_SYSTEM,
|
| 537 |
)
|
| 538 |
+
history_context=""
|
| 539 |
+
try:
|
| 540 |
+
history_context=_format_recent_thread_history(
|
| 541 |
+
tid,
|
| 542 |
+
limit=12,
|
| 543 |
+
max_chars=24000,
|
| 544 |
+
)
|
| 545 |
+
except Exception:
|
| 546 |
+
history_context=""
|
| 547 |
|
| 548 |
harness_prompt=(
|
| 549 |
"[APPLICATION_CONTEXT]\n"
|
| 550 |
+ app_context
|
| 551 |
+ "\n[/APPLICATION_CONTEXT]\n\n"
|
| 552 |
+
+ (
|
| 553 |
+
"[PRIOR_CONVERSATION_HISTORY]\n"
|
| 554 |
+
+ history_context
|
| 555 |
+
+ "\n[/PRIOR_CONVERSATION_HISTORY]\n\n"
|
| 556 |
+
+ "[HISTORY_INSTRUCTION]\n"
|
| 557 |
+
+ "Use prior conversation only to resolve references and continuity. "
|
| 558 |
+
"The current user message has priority over older content.\n"
|
| 559 |
+
+ "[/HISTORY_INSTRUCTION]\n\n"
|
| 560 |
+
if history_context else ""
|
| 561 |
+
)
|
| 562 |
+ "[CURRENT_USER_MESSAGE]\n"
|
| 563 |
+ prompt
|
| 564 |
+ "\n[/CURRENT_USER_MESSAGE]"
|
|
|
|
| 610 |
"Codex Harness 没有返回有效文本。"
|
| 611 |
)
|
| 612 |
|
| 613 |
+
tool_names=tuple(getattr(result,"tool_names",()) or ())
|
| 614 |
+
tool_events=tuple(getattr(result,"tool_events",()) or ())
|
| 615 |
+
export_tool_completed=any(
|
| 616 |
+
name.endswith("marine_export")
|
| 617 |
+
or name.endswith("marine_export_range")
|
| 618 |
+
or name.endswith("_export")
|
| 619 |
+
for name in tool_names
|
| 620 |
+
)
|
| 621 |
+
export_error=_ocean_export_execution_error(
|
| 622 |
+
prompt,
|
| 623 |
+
export_tool_completed=export_tool_completed,
|
| 624 |
+
tool_result_text="\n".join(tool_events),
|
| 625 |
+
final_answer=final_answer,
|
| 626 |
+
)
|
| 627 |
+
if export_error:
|
| 628 |
+
raise RuntimeError(export_error)
|
| 629 |
+
|
| 630 |
log.info(
|
| 631 |
"Codex Harness completed: "
|
| 632 |
"thread=%s model=%s reason=%s uploads=%s",
|
|
|
|
| 664 |
len(pending_uploads),
|
| 665 |
)
|
| 666 |
|
| 667 |
+
public_error=_public_error(str(exc))
|
| 668 |
yield out(
|
| 669 |
"error",
|
| 670 |
{
|
| 671 |
+
"text":public_error,
|
|
|
|
|
|
|
| 672 |
"stage":"harness",
|
| 673 |
},
|
| 674 |
)
|
|
|
|
| 690 |
|
| 691 |
|
| 692 |
def _is_marine_health_prompt(prompt: str) -> bool:
|
| 693 |
+
"""Recognize actual connectivity/status questions, not any domain mention."""
|
| 694 |
+
text=str(prompt or "").strip().lower()
|
| 695 |
+
if not text:
|
| 696 |
+
return False
|
| 697 |
+
explicit_phrases=(
|
| 698 |
"海洋数据服务器连接", "检查海洋数据服务器", "数据服务器连接",
|
| 699 |
+
"三个域是否在线", "三个数据域是否在线", "marine health",
|
| 700 |
+
"marine server health",
|
| 701 |
+
)
|
| 702 |
+
if any(term in text for term in explicit_phrases):
|
| 703 |
+
return True
|
| 704 |
+
status_terms=(
|
| 705 |
+
"在线","离线","连接","连通","状态","健康","可用","不可用",
|
| 706 |
+
"正常吗","是否正常","reachable","online","offline","status","health",
|
| 707 |
)
|
| 708 |
+
domain_terms=("ocean","tuna","squid","marine","数据服务器","数据域")
|
| 709 |
+
return any(x in text for x in status_terms) and any(x in text for x in domain_terms)
|
| 710 |
|
| 711 |
|
| 712 |
def _is_fisheries_inventory_prompt(prompt: str) -> bool:
|
|
|
|
| 839 |
|
| 840 |
|
| 841 |
async def _direct_marine_health_answer():
|
| 842 |
+
"""Query live domain status without inferring unavailable states."""
|
| 843 |
+
httpx_module=globals().get("httpx")
|
| 844 |
if httpx_module is None:
|
| 845 |
try:
|
| 846 |
import httpx as httpx_module
|
| 847 |
except Exception as exc:
|
| 848 |
return f"海洋数据服务器连接检查失败:HTTP 客户端不可用({exc})"
|
| 849 |
+
base=str(globals().get("MARINE_API_URL") or "").rstrip("/")
|
| 850 |
if not base:
|
| 851 |
return "海洋数据服务器未配置 MARINE_API_URL。"
|
| 852 |
|
| 853 |
+
def status_label(value):
|
| 854 |
+
if isinstance(value,dict):
|
| 855 |
+
value=value.get("status",value.get("online",value.get("available")))
|
| 856 |
+
if value is True:
|
| 857 |
+
return "在线"
|
| 858 |
+
if value is False:
|
| 859 |
+
return "离线/不可用"
|
| 860 |
+
low=str(value or "").strip().lower()
|
| 861 |
+
if low in {"ok","online","ready","available","healthy","true","1"}:
|
| 862 |
+
return "在线"
|
| 863 |
+
if low in {"offline","down","unavailable","error","false","0"}:
|
| 864 |
+
return "离线/不可用"
|
| 865 |
+
return "未确认"
|
| 866 |
+
|
| 867 |
+
candidates=[f"{base}/domains"]
|
| 868 |
if not base.endswith("/marine"):
|
| 869 |
+
candidates.append(f"{base}/marine/domains")
|
| 870 |
+
last_error=""
|
| 871 |
+
async with httpx_module.AsyncClient(timeout=12.0,follow_redirects=True) as client:
|
|
|
|
| 872 |
for url in candidates:
|
| 873 |
try:
|
| 874 |
+
response=await client.get(url)
|
| 875 |
+
if not response.is_success:
|
| 876 |
+
last_error=f"HTTP {response.status_code}"
|
| 877 |
+
continue
|
| 878 |
+
payload=response.json()
|
| 879 |
+
domain_payload=payload.get("domains") if isinstance(payload,dict) else None
|
| 880 |
+
if not isinstance(domain_payload,(dict,list)):
|
| 881 |
+
domain_payload=payload if isinstance(payload,(dict,list)) else None
|
| 882 |
+
labels={key:"未确认" for key in ("ocean","tuna","squid")}
|
| 883 |
+
if isinstance(domain_payload,dict):
|
| 884 |
+
for key in labels:
|
| 885 |
+
if key in domain_payload:
|
| 886 |
+
labels[key]=status_label(domain_payload.get(key))
|
| 887 |
+
elif isinstance(domain_payload,list):
|
| 888 |
+
present={str(x.get("name") if isinstance(x,dict) else x).lower() for x in domain_payload}
|
| 889 |
+
for key in labels:
|
| 890 |
+
labels[key]="在线" if key in present else "未确认"
|
| 891 |
+
return (
|
| 892 |
+
"Marine 数据服务已连通。\n"
|
| 893 |
+
f"- Ocean:{labels['ocean']}\n"
|
| 894 |
+
f"- Tuna:{labels['tuna']}\n"
|
| 895 |
+
f"- Squid:{labels['squid']}\n"
|
| 896 |
+
"未确认表示服务器响应中没有足够状态字段,平台不会把它自动当成在线。"
|
| 897 |
+
)
|
| 898 |
+
except Exception as exc:
|
| 899 |
+
last_error=str(exc)
|
| 900 |
+
|
| 901 |
+
# Fallback health only proves the API is reachable, not that each domain is online.
|
| 902 |
+
health_urls=[f"{base}/health"]
|
| 903 |
+
if not base.endswith("/marine"):
|
| 904 |
+
health_urls.append(f"{base}/marine/health")
|
| 905 |
+
async with httpx_module.AsyncClient(timeout=12.0,follow_redirects=True) as client:
|
| 906 |
+
for url in health_urls:
|
| 907 |
+
try:
|
| 908 |
+
response=await client.get(url)
|
| 909 |
if response.is_success:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 910 |
return (
|
| 911 |
+
"Marine API 可以连接,但当前未取得 Ocean/Tuna/Squid 的逐域状态。"
|
| 912 |
+
"请在“设置 → 系统健康”中重新检测详细状态。"
|
|
|
|
|
|
|
| 913 |
)
|
| 914 |
+
last_error=f"HTTP {response.status_code}"
|
| 915 |
except Exception as exc:
|
| 916 |
+
last_error=str(exc)
|
| 917 |
return f"海洋数据服务器连接检查失败:{last_error[:240]}"
|
| 918 |
|
| 919 |
|
static/js/app.js
CHANGED
|
@@ -340,7 +340,7 @@ function persist(role,text,meta=""){
|
|
| 340 |
if(role==="assistant"&&meta!=="error")refreshSessionSummary(x,true);
|
| 341 |
setUpdated(x);save();hist()
|
| 342 |
}
|
| 343 |
-
function historyPayload(x,limit=
|
| 344 |
if(!x)return[];
|
| 345 |
const items=[];
|
| 346 |
for(const m of (x.messages||[])){
|
|
|
|
| 340 |
if(role==="assistant"&&meta!=="error")refreshSessionSummary(x,true);
|
| 341 |
setUpdated(x);save();hist()
|
| 342 |
}
|
| 343 |
+
function historyPayload(x,limit=12){
|
| 344 |
if(!x)return[];
|
| 345 |
const items=[];
|
| 346 |
for(const m of (x.messages||[])){
|
tests/test_agent_reliability_v4620.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
+
|
| 4 |
+
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
+
|
| 7 |
+
def test_harness_receives_recent_conversation_history():
|
| 8 |
+
py=(ROOT/"services/chat_runtime.py").read_text(encoding="utf-8")
|
| 9 |
+
assert "_format_recent_thread_history(" in py
|
| 10 |
+
assert "[PRIOR_CONVERSATION_HISTORY]" in py
|
| 11 |
+
assert "max_chars=24000" in py
|
| 12 |
+
|
| 13 |
+
def test_health_intent_does_not_trigger_on_domain_names_alone():
|
| 14 |
+
py=(ROOT/"services/chat_runtime.py").read_text(encoding="utf-8")
|
| 15 |
+
block=py[py.index("def _is_marine_health_prompt"):py.index("def _is_fisheries_inventory_prompt")]
|
| 16 |
+
assert '"ocean、tuna、squid"' not in block
|
| 17 |
+
assert "status_terms" in block
|
| 18 |
+
assert "domain_terms" in block
|
| 19 |
+
|
| 20 |
+
def test_direct_health_never_defaults_all_domains_online():
|
| 21 |
+
py=(ROOT/"services/chat_runtime.py").read_text(encoding="utf-8")
|
| 22 |
+
block=py[py.index("async def _direct_marine_health_answer"):py.index("def _is_explicit_new_data_query")]
|
| 23 |
+
assert 'labels={key:"未确认"' in block
|
| 24 |
+
assert '/domains' in block
|
| 25 |
+
assert "平台不会把它自动当成在线" in block
|
| 26 |
+
|
| 27 |
+
def test_native_harness_preserves_tool_evidence():
|
| 28 |
+
py=(ROOT/"codex_native_harness.py").read_text(encoding="utf-8")
|
| 29 |
+
assert "tool_names: tuple[str, ...]" in py
|
| 30 |
+
assert "_tool_names_from_event" in py
|
| 31 |
+
assert "tool_events=tuple(tool_events)" in py
|
| 32 |
+
|
| 33 |
+
def test_harness_export_is_fail_closed():
|
| 34 |
+
py=(ROOT/"services/chat_runtime.py").read_text(encoding="utf-8")
|
| 35 |
+
assert 'tool_names=tuple(getattr(result,"tool_names"' in py
|
| 36 |
+
assert "export_tool_completed=any(" in py
|
| 37 |
+
assert "_ocean_export_execution_error(" in py
|
| 38 |
+
|
| 39 |
+
def test_adapter_does_not_store_shared_mutable_session_id():
|
| 40 |
+
py=(ROOT/"codex_harness.py").read_text(encoding="utf-8")
|
| 41 |
+
assert "request_session_id" in py
|
| 42 |
+
assert "self._session_id =" not in py
|
| 43 |
+
|
| 44 |
+
def test_harness_errors_are_sanitized():
|
| 45 |
+
py=(ROOT/"services/chat_runtime.py").read_text(encoding="utf-8")
|
| 46 |
+
assert "public_error=_public_error(str(exc))" in py
|
| 47 |
+
assert '"text":public_error' in py
|
| 48 |
+
|
| 49 |
+
def test_frontend_sends_more_recent_context():
|
| 50 |
+
js=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
| 51 |
+
assert "function historyPayload(x,limit=12)" in js
|
tests/test_api_entry_preflight_v456.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_guard_is_before_auth_and_dispatch():
|
| 8 |
chat=(ROOT/"routes"/"chat.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_guard_is_before_auth_and_dispatch():
|
| 8 |
chat=(ROOT/"routes"/"chat.py").read_text(encoding="utf-8")
|
tests/test_chat_lifecycle_progress_v393.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_393():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_frontend_lifecycle_progress():
|
| 9 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_393():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_frontend_lifecycle_progress():
|
| 9 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_clarification_ui_v454.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_missing_date_reuses_canonical_region_bbox():
|
| 8 |
rt=(ROOT/"services"/"chat_runtime.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_missing_date_reuses_canonical_region_bbox():
|
| 8 |
rt=(ROOT/"services"/"chat_runtime.py").read_text(encoding="utf-8")
|
tests/test_classification_cleanup_v466.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_seaaroundus_alias():
|
| 8 |
py=(ROOT/"sidebar_catalog.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_seaaroundus_alias():
|
| 8 |
py=(ROOT/"sidebar_catalog.py").read_text(encoding="utf-8")
|
tests/test_context_and_multitask_finalize_v451.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_new_query_slot_reset():
|
| 8 |
rt=(ROOT/"services"/"chat_runtime.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_new_query_slot_reset():
|
| 8 |
rt=(ROOT/"services"/"chat_runtime.py").read_text(encoding="utf-8")
|
tests/test_conversation_summary_v4613.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_frontend_auto_summary_and_manual_override():
|
| 8 |
js=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_frontend_auto_summary_and_manual_override():
|
| 8 |
js=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
tests/test_download_host_authorization_v460.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_batch_url_authorization_helper_exists():
|
| 8 |
py=(ROOT/"routes"/"downloads.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_batch_url_authorization_helper_exists():
|
| 8 |
py=(ROOT/"routes"/"downloads.py").read_text(encoding="utf-8")
|
tests/test_download_opfs_fallback_v459.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_opfs_is_probed_not_assumed():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_opfs_is_probed_not_assumed():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_download_overlay_v4618.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_native_download_handoff_finishes_overlay():
|
| 8 |
js=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_native_download_handoff_finishes_overlay():
|
| 8 |
js=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
tests/test_download_progress_v391.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_391():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_p1_label_removed():
|
| 9 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_391():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_p1_label_removed():
|
| 9 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_download_resilience_v422.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_refresh_route_registered():
|
| 9 |
t=(ROOT/"routes"/"ocean_batch.py").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_refresh_route_registered():
|
| 9 |
t=(ROOT/"routes"/"ocean_batch.py").read_text(encoding="utf-8")
|
tests/test_frontend_preflight_v457.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_frontend_preflight_exists_before_progress():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_frontend_preflight_exists_before_progress():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_history_dedupe_recent_summary_v4614.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_frontend_dedupe_and_merge():
|
| 8 |
js=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_frontend_dedupe_and_merge():
|
| 8 |
js=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
tests/test_history_sidebar_v373.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_373():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_project_history_backend():
|
| 9 |
route=(ROOT/"routes"/"project_package.py").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_373():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_project_history_backend():
|
| 9 |
route=(ROOT/"routes"/"project_package.py").read_text(encoding="utf-8")
|
tests/test_large_download_jobs_v400.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_400():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_download_job_backend():
|
| 9 |
route=(ROOT/"routes"/"downloads.py").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_400():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_download_job_backend():
|
| 9 |
route=(ROOT/"routes"/"downloads.py").read_text(encoding="utf-8")
|
tests/test_manual_tasks_v469.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_manual_task_backend_exists():
|
| 8 |
service=(ROOT/"services/manual_tasks.py").read_text(encoding="utf-8")
|
|
@@ -27,4 +27,4 @@ def test_frontend_new_task_controls():
|
|
| 27 |
assert "标记完成" in js
|
| 28 |
assert "重新打开" in js
|
| 29 |
assert "manual-delete" in js
|
| 30 |
-
assert "账号
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_manual_task_backend_exists():
|
| 8 |
service=(ROOT/"services/manual_tasks.py").read_text(encoding="utf-8")
|
|
|
|
| 27 |
assert "标记完成" in js
|
| 28 |
assert "重新打开" in js
|
| 29 |
assert "manual-delete" in js
|
| 30 |
+
assert "账号同步:" in js and "可跨设备同步" in js and "服务器会话" in js
|
tests/test_merged_health_v433.py
CHANGED
|
@@ -3,7 +3,7 @@ from services.ocean_batch import parse_ocean_batch_request
|
|
| 3 |
ROOT=Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_merged_version():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_ocean_month_batch_survives_merge():
|
| 9 |
p=parse_ocean_batch_request("查询 2002 年 8 月西北太平洋的 SST 数据,并导出为 CSV 文件供我下载")
|
|
|
|
| 3 |
ROOT=Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_merged_version():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_ocean_month_batch_survives_merge():
|
| 9 |
p=parse_ocean_batch_request("查询 2002 年 8 月西北太平洋的 SST 数据,并导出为 CSV 文件供我下载")
|
tests/test_multitask_observability_v442.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_frontend_sends_multitask_trace_headers():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_frontend_sends_multitask_trace_headers():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_multitask_sse_finalize_v452.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_parallel_sse_uses_real_blank_line_separator():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_parallel_sse_uses_real_blank_line_separator():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_noaa_ramldb_roles_v465.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_noaa_and_ramldb_aliases():
|
| 8 |
py=(ROOT/"sidebar_catalog.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_noaa_and_ramldb_aliases():
|
| 8 |
py=(ROOT/"sidebar_catalog.py").read_text(encoding="utf-8")
|
tests/test_ocean_batch_downloads_v420.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_420():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_manifest_has_filename_and_sizes():
|
| 9 |
svc=(ROOT/"services"/"ocean_batch.py").read_text(encoding="utf-8")
|
|
@@ -17,13 +17,13 @@ def test_frontend_has_one_click_batch_download():
|
|
| 17 |
assert "function startOceanBatchDownloadAll" in js
|
| 18 |
assert "function runOceanBatchDownloadQueue" in js
|
| 19 |
assert "function waitManagedDownloadStatus" in js
|
| 20 |
-
assert "下载
|
| 21 |
assert "查看文件" in js
|
| 22 |
|
| 23 |
def test_batch_download_uses_managed_range_jobs():
|
| 24 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
| 25 |
assert 'j("/api/download/jobs"' in js
|
| 26 |
-
assert "triggerBrowserSave(
|
| 27 |
assert "resume_supported" in js
|
| 28 |
assert "30 秒无新字节" in js
|
| 29 |
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_420():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_manifest_has_filename_and_sizes():
|
| 9 |
svc=(ROOT/"services"/"ocean_batch.py").read_text(encoding="utf-8")
|
|
|
|
| 17 |
assert "function startOceanBatchDownloadAll" in js
|
| 18 |
assert "function runOceanBatchDownloadQueue" in js
|
| 19 |
assert "function waitManagedDownloadStatus" in js
|
| 20 |
+
assert "打包 ZIP 下载" in js and "逐个下载" in js
|
| 21 |
assert "查看文件" in js
|
| 22 |
|
| 23 |
def test_batch_download_uses_managed_range_jobs():
|
| 24 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
| 25 |
assert 'j("/api/download/jobs"' in js
|
| 26 |
+
assert "triggerBrowserSave(job.stream_url" in js
|
| 27 |
assert "resume_supported" in js
|
| 28 |
assert "30 秒无新字节" in js
|
| 29 |
|
tests/test_ocean_batch_routing_v421.py
CHANGED
|
@@ -4,7 +4,7 @@ from services.ocean_batch import parse_ocean_batch_request
|
|
| 4 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 5 |
|
| 6 |
def test_version_421():
|
| 7 |
-
assert (ROOT/
|
| 8 |
|
| 9 |
def test_exact_user_month_query_routes_to_batch():
|
| 10 |
p=parse_ocean_batch_request("查询 2002 年 8 月西北太平洋的 SST 数据,并导出为 CSV 文件供我下载")
|
|
|
|
| 4 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 5 |
|
| 6 |
def test_version_421():
|
| 7 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 8 |
|
| 9 |
def test_exact_user_month_query_routes_to_batch():
|
| 10 |
p=parse_ocean_batch_request("查询 2002 年 8 月西北太平洋的 SST 数据,并导出为 CSV 文件供我下载")
|
tests/test_ocean_batch_v410.py
CHANGED
|
@@ -4,7 +4,7 @@ from services.ocean_batch import parse_ocean_batch_request
|
|
| 4 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 5 |
|
| 6 |
def test_version_410():
|
| 7 |
-
assert (ROOT/
|
| 8 |
|
| 9 |
def test_month_three_variable_batch_plan():
|
| 10 |
p=parse_ocean_batch_request("查询并导出 2002 年 8 月西北太平洋 120°E–140°E、20°N–40°N 的 SST、SSH、CHL 数据,并打包下载")
|
|
|
|
| 4 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 5 |
|
| 6 |
def test_version_410():
|
| 7 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 8 |
|
| 9 |
def test_month_three_variable_batch_plan():
|
| 10 |
p=parse_ocean_batch_request("查询并导出 2002 年 8 月西北太平洋 120°E–140°E、20°N–40°N 的 SST、SSH、CHL 数据,并打包下载")
|
tests/test_ocean_batch_zip_manifest_v4619.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_zip_backend_routes_exist():
|
| 8 |
py=(ROOT/"routes/ocean_batch.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_zip_backend_routes_exist():
|
| 8 |
py=(ROOT/"routes/ocean_batch.py").read_text(encoding="utf-8")
|
tests/test_ocean_date_default_v453.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_missing_date_never_defaults_to_today():
|
| 8 |
rt=(ROOT/"services"/"chat_runtime.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_missing_date_never_defaults_to_today():
|
| 8 |
rt=(ROOT/"services"/"chat_runtime.py").read_text(encoding="utf-8")
|
tests/test_ocean_download_url_base_v462.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_generic_public_base_not_used():
|
| 8 |
py=(ROOT/"services"/"ocean_batch.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_generic_public_base_not_used():
|
| 8 |
py=(ROOT/"services"/"ocean_batch.py").read_text(encoding="utf-8")
|
tests/test_p0_finish_v380.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib, re, subprocess, shutil
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_380():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_chat_runtime_extracted():
|
| 9 |
ui=(ROOT/"ui_server.py").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_380():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_chat_runtime_extracted():
|
| 9 |
ui=(ROOT/"ui_server.py").read_text(encoding="utf-8")
|
tests/test_p0_phase2_v371.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_frontend_feature_modules_exist():
|
| 9 |
html=(ROOT/"app.html").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_frontend_feature_modules_exist():
|
| 9 |
html=(ROOT/"app.html").read_text(encoding="utf-8")
|
tests/test_p0_phase3_v372.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_372():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_route_modules_exist():
|
| 9 |
for name in ("datasets.py","user_state.py","project_package.py","data_health.py"):
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_372():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_route_modules_exist():
|
| 9 |
for name in ("datasets.py","user_state.py","project_package.py","data_health.py"):
|
tests/test_platform_reliability_v450.py
CHANGED
|
@@ -6,7 +6,7 @@ from services.ocean_batch import parse_ocean_batch_request
|
|
| 6 |
ROOT=Path(__file__).resolve().parents[1]
|
| 7 |
|
| 8 |
def test_version():
|
| 9 |
-
assert (ROOT/
|
| 10 |
|
| 11 |
def test_squid_center_uses_repository_membership():
|
| 12 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
@@ -15,7 +15,7 @@ def test_squid_center_uses_repository_membership():
|
|
| 15 |
assert "file_count_by_repository" in api
|
| 16 |
assert "domains.includes(domain)" in js
|
| 17 |
assert "squid_file_count" in js
|
| 18 |
-
assert "实时
|
| 19 |
|
| 20 |
def test_single_ocean_export_forces_managed_proxy():
|
| 21 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 6 |
ROOT=Path(__file__).resolve().parents[1]
|
| 7 |
|
| 8 |
def test_version():
|
| 9 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 10 |
|
| 11 |
def test_squid_center_uses_repository_membership():
|
| 12 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 15 |
assert "file_count_by_repository" in api
|
| 16 |
assert "domains.includes(domain)" in js
|
| 17 |
assert "squid_file_count" in js
|
| 18 |
+
assert "Hugging Face main 实时文件树" in js
|
| 19 |
|
| 20 |
def test_single_ocean_export_forces_managed_proxy():
|
| 21 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_product_finish_v4615.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_system_health_is_settings_embedded_and_modular():
|
| 8 |
app=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_system_health_is_settings_embedded_and_modular():
|
| 8 |
app=(ROOT/"static/js/app.js").read_text(encoding="utf-8")
|
tests/test_project_package_download_v4617.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_project_package_download_is_capability_url():
|
| 8 |
py=(ROOT/"routes/project_package.py").read_text(encoding="utf-8")
|
|
@@ -21,4 +21,4 @@ def test_same_origin_download_probes_before_native_save():
|
|
| 21 |
def test_project_download_button_explains_browser_handoff():
|
| 22 |
js=(ROOT/"static/js/project-package.js").read_text(encoding="utf-8")
|
| 23 |
assert "正在交给浏览器" in js
|
| 24 |
-
assert "已交给浏览器下载" in js
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_project_package_download_is_capability_url():
|
| 8 |
py=(ROOT/"routes/project_package.py").read_text(encoding="utf-8")
|
|
|
|
| 21 |
def test_project_download_button_explains_browser_handoff():
|
| 22 |
js=(ROOT/"static/js/project-package.js").read_text(encoding="utf-8")
|
| 23 |
assert "正在交给浏览器" in js
|
| 24 |
+
assert "已交给浏览器;实际完成状态请看浏览器下载栏" in js
|
tests/test_quality_center_v362.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_371():
|
| 6 |
-
assert (ROOT
|
| 7 |
|
| 8 |
def test_native_health_backend():
|
| 9 |
text = (ROOT / "routes" / "data_health.py").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_371():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_native_health_backend():
|
| 9 |
text = (ROOT / "routes" / "data_health.py").read_text(encoding="utf-8")
|
tests/test_quality_trust_v361.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version_current():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_quality_confidence_is_now_native_api_metric():
|
| 8 |
text=(ROOT/"routes"/"data_health.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version_current():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_quality_confidence_is_now_native_api_metric():
|
| 8 |
text=(ROOT/"routes"/"data_health.py").read_text(encoding="utf-8")
|
tests/test_reference_cleanup_v468.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_reference_and_reproducibility_are_auxiliary():
|
| 8 |
py=(ROOT/"routes"/"datasets.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_reference_and_reproducibility_are_auxiliary():
|
| 8 |
py=(ROOT/"routes"/"datasets.py").read_text(encoding="utf-8")
|
tests/test_release_stability.py
CHANGED
|
@@ -7,7 +7,7 @@ def test_version_is_single_source():
|
|
| 7 |
version = (ROOT / "VERSION").read_text(encoding="utf-8").strip()
|
| 8 |
ui = (ROOT / "ui_server.py").read_text(encoding="utf-8")
|
| 9 |
html = (ROOT / "app.html").read_text(encoding="utf-8")
|
| 10 |
-
assert version ==
|
| 11 |
assert 'with_name("VERSION")' in ui
|
| 12 |
assert "__APP_VERSION__" in html
|
| 13 |
|
|
|
|
| 7 |
version = (ROOT / "VERSION").read_text(encoding="utf-8").strip()
|
| 8 |
ui = (ROOT / "ui_server.py").read_text(encoding="utf-8")
|
| 9 |
html = (ROOT / "app.html").read_text(encoding="utf-8")
|
| 10 |
+
assert version == '4.6.20'
|
| 11 |
assert 'with_name("VERSION")' in ui
|
| 12 |
assert "__APP_VERSION__" in html
|
| 13 |
|
tests/test_resumable_batch_download_v458.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_network_loss_pauses_not_fails_all():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_network_loss_pauses_not_fails_all():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_route_region_clarification_v455.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_route_guard_exists_before_agent_dispatch():
|
| 8 |
chat=(ROOT/"routes"/"chat.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_route_guard_exists_before_agent_dispatch():
|
| 8 |
chat=(ROOT/"routes"/"chat.py").read_text(encoding="utf-8")
|
tests/test_runtime_hotfix_v376.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_376():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_no_stray_async_before_sidebar_toggle():
|
| 9 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_376():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_no_stray_async_before_sidebar_toggle():
|
| 9 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_sidebar_collapse_v374.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_374():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_sidebar_toggle_markup():
|
| 9 |
html=(ROOT/"app.html").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_374():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_sidebar_toggle_markup():
|
| 9 |
html=(ROOT/"app.html").read_text(encoding="utf-8")
|
tests/test_sidebar_partial_collapse_v375.py
CHANGED
|
@@ -3,7 +3,7 @@ import pathlib
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_375():
|
| 6 |
-
assert (ROOT/
|
| 7 |
|
| 8 |
def test_sidebar_order_and_groups():
|
| 9 |
html=(ROOT/"app.html").read_text(encoding="utf-8")
|
|
|
|
| 3 |
ROOT=pathlib.Path(__file__).resolve().parents[1]
|
| 4 |
|
| 5 |
def test_version_375():
|
| 6 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 7 |
|
| 8 |
def test_sidebar_order_and_groups():
|
| 9 |
html=(ROOT/"app.html").read_text(encoding="utf-8")
|
tests/test_smart_progress_avatar_sync_v441.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_simple_chat_hides_progress_until_needed():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_simple_chat_hides_progress_until_needed():
|
| 8 |
js=(ROOT/"static"/"js"/"app.js").read_text(encoding="utf-8")
|
tests/test_source_mapping_roles_v464.py
CHANGED
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
-
assert (ROOT/
|
| 6 |
|
| 7 |
def test_new_source_mappings():
|
| 8 |
py=(ROOT/"sidebar_catalog.py").read_text(encoding="utf-8")
|
|
|
|
| 2 |
ROOT=Path(__file__).resolve().parents[1]
|
| 3 |
|
| 4 |
def test_version():
|
| 5 |
+
assert (ROOT/'VERSION').read_text(encoding='utf-8').strip()=='4.6.20'
|
| 6 |
|
| 7 |
def test_new_source_mappings():
|
| 8 |
py=(ROOT/"sidebar_catalog.py").read_text(encoding="utf-8")
|