落地并存测服全端:智能体 Graph/路由、后台切 8180、主账与部署脚本齐备,便于线上重发与验收。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-09-13 21:15:58 +08:00
co-authored by Cursor
parent 0eb1adecc8
commit 8103b3b651
143 changed files with 8968 additions and 277 deletions
@@ -0,0 +1,162 @@
"""
停等账仓储壳:suspend_wait(waitVersion)。
本文件职责:登记/关闭停点;与 Graph interrupt、H5 token 对齐的版本号。
禁止:用本表冒充主账六态;禁止用户文字伪造 Worker 完成。
"""
from __future__ import annotations
import logging
import threading
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any, Optional
from agent.runtime_db import assert_safe_database, connect_psycopg
logger = logging.getLogger(__name__)
def _utcnow() -> datetime:
return datetime.now(timezone.utc)
@dataclass
class SuspendRecord:
"""一条停等记录。"""
thread_id: str
wait_version: int
pause_name: str = ""
inquiry_no: str = ""
status: str = "open"
payload: dict[str, Any] = field(default_factory=dict)
class MemorySuspendStore:
"""内存停等壳。"""
def __init__(self) -> None:
self._rows: dict[tuple[str, int], SuspendRecord] = {}
self._lock = threading.Lock()
def open_wait(self, record: SuspendRecord) -> None:
key = (record.thread_id, record.wait_version)
with self._lock:
self._rows[key] = SuspendRecord(
thread_id=record.thread_id,
wait_version=record.wait_version,
pause_name=record.pause_name,
inquiry_no=record.inquiry_no,
status="open",
payload=dict(record.payload),
)
logger.info(
"suspend.memory.open thread=%s wait=%s pause=%s",
record.thread_id,
record.wait_version,
record.pause_name,
)
def get(self, thread_id: str, wait_version: int) -> Optional[SuspendRecord]:
with self._lock:
rec = self._rows.get((thread_id, wait_version))
if rec is None:
return None
return SuspendRecord(
thread_id=rec.thread_id,
wait_version=rec.wait_version,
pause_name=rec.pause_name,
inquiry_no=rec.inquiry_no,
status=rec.status,
payload=dict(rec.payload),
)
def close_wait(self, thread_id: str, wait_version: int) -> bool:
with self._lock:
rec = self._rows.get((thread_id, wait_version))
if rec is None:
return False
rec.status = "closed"
return True
class PostgresSuspendStore:
"""PG 停等壳(表 suspend_wait)。"""
def __init__(self, dsn: str) -> None:
assert_safe_database(dsn)
self._dsn = dsn
def open_wait(self, record: SuspendRecord) -> None:
import json
with connect_psycopg(self._dsn) as conn:
conn.execute(
"""
INSERT INTO suspend_wait (
thread_id, wait_version, pause_name, inquiry_no, status, payload
) VALUES (%s, %s, %s, %s, 'open', %s::jsonb)
ON CONFLICT (thread_id, wait_version) DO UPDATE SET
pause_name = EXCLUDED.pause_name,
inquiry_no = EXCLUDED.inquiry_no,
status = 'open',
payload = EXCLUDED.payload,
closed_at = NULL
""",
(
record.thread_id,
record.wait_version,
record.pause_name,
record.inquiry_no,
json.dumps(record.payload, ensure_ascii=False),
),
)
conn.commit()
logger.info(
"suspend.pg.open thread=%s wait=%s",
record.thread_id,
record.wait_version,
)
def get(self, thread_id: str, wait_version: int) -> Optional[SuspendRecord]:
with connect_psycopg(self._dsn) as conn:
row = conn.execute(
"""
SELECT thread_id, wait_version, pause_name, inquiry_no, status, payload
FROM suspend_wait
WHERE thread_id = %s AND wait_version = %s
""",
(thread_id, wait_version),
).fetchone()
if not row:
return None
return SuspendRecord(
thread_id=str(row[0]),
wait_version=int(row[1]),
pause_name=str(row[2] or ""),
inquiry_no=str(row[3] or ""),
status=str(row[4] or ""),
payload=dict(row[5] or {}),
)
def close_wait(self, thread_id: str, wait_version: int) -> bool:
with connect_psycopg(self._dsn) as conn:
cur = conn.execute(
"""
UPDATE suspend_wait
SET status = 'closed', closed_at = %s
WHERE thread_id = %s AND wait_version = %s AND status = 'open'
""",
(_utcnow(), thread_id, wait_version),
)
conn.commit()
return cur.rowcount > 0
def create_suspend_store(*, dsn: str = "", backend: str = "auto"):
"""工厂:Memory 或 PG。"""
if backend == "memory" or not dsn:
return MemorySuspendStore()
return PostgresSuspendStore(dsn)