chore(db): add ten-project chat seed migration and generator script
Provide SQL migration and Python helper to import review demo sessions and seed messages from tenProjectsSeed.json into Postgres. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
seed_ten_projects_chat.py
|
||||
将 10 个评审项目的 30 个会话与 240 条种子对话消息完整写入 PostgreSQL 数据库
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
def main():
|
||||
seed_path = "web/src/data/seeds/tenProjectsSeed.json"
|
||||
with open(seed_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
sessions = data.get("sessions", [])
|
||||
messages = data.get("messages", [])
|
||||
|
||||
print(f"读取到 {len(sessions)} 个会话,{len(messages)} 条种子消息。")
|
||||
|
||||
sql_lines = [
|
||||
"-- ==============================================================================",
|
||||
"-- 迁移脚本: 10 个评审项目会话与种子消息持久化导入",
|
||||
"-- ==============================================================================",
|
||||
"BEGIN;",
|
||||
]
|
||||
|
||||
# 1. 导入 chat_sessions
|
||||
sess_user_map = {}
|
||||
for s in sessions:
|
||||
sid = s["sessionId"]
|
||||
pid = s.get("projectId", 6001)
|
||||
uid = s.get("userId", 1)
|
||||
sess_user_map[sid] = uid
|
||||
title = s.get("title", "项目协同会话").replace("'", "''")
|
||||
stage = s.get("stage", "V0.5")
|
||||
|
||||
sql_lines.append(f"""
|
||||
INSERT INTO chat_sessions (session_id, project_id, user_id, title, current_stage, pending_exp, status, created_at, updated_at)
|
||||
VALUES ('{sid}', {pid}, {uid}, '{title}', '{stage}', '{{}}', 'active', '2026-09-11 08:00:00+08', '2026-09-11 08:00:00+08')
|
||||
ON CONFLICT (session_id) DO UPDATE SET
|
||||
project_id = EXCLUDED.project_id,
|
||||
user_id = EXCLUDED.user_id,
|
||||
title = EXCLUDED.title,
|
||||
current_stage = EXCLUDED.current_stage,
|
||||
updated_at = EXCLUDED.updated_at;
|
||||
""")
|
||||
|
||||
# 2. 清理这 30 个 session 的旧测试数据以保持干净
|
||||
sids_list = "('" + "', '".join(sess_user_map.keys()) + "')"
|
||||
sql_lines.append(f"DELETE FROM chat_messages WHERE session_id IN {sids_list};")
|
||||
sql_lines.append(f"DELETE FROM chat_read_positions WHERE session_id IN {sids_list};")
|
||||
|
||||
# 3. 导入 240 条消息
|
||||
base_time = datetime(2026, 9, 11, 9, 0, 0)
|
||||
# 按会话分组
|
||||
sess_msgs = {}
|
||||
for m in messages:
|
||||
sid = m["sessionId"]
|
||||
sess_msgs.setdefault(sid, []).append(m)
|
||||
|
||||
last_msg_id_map = {}
|
||||
|
||||
for sid, mlist in sess_msgs.items():
|
||||
uid = sess_user_map.get(sid, 1)
|
||||
curr_time = base_time
|
||||
|
||||
for idx, m in enumerate(mlist):
|
||||
role = m.get("role", "user")
|
||||
content = m.get("content", "").replace("'", "''")
|
||||
intent = m.get("intentTag", "").replace("'", "''")
|
||||
category = m.get("category", "general").replace("'", "''")
|
||||
|
||||
# 解析原始时间戳如 "09:14"
|
||||
ts = m.get("timestamp", "")
|
||||
if ts and ":" in ts:
|
||||
try:
|
||||
parts = ts.split(":")
|
||||
curr_time = datetime(2026, 9, 11, int(parts[0]), int(parts[1]), idx % 60)
|
||||
except Exception:
|
||||
curr_time += timedelta(seconds=15)
|
||||
else:
|
||||
curr_time += timedelta(seconds=15)
|
||||
|
||||
time_str = curr_time.strftime("%Y-%m-%d %H:%M:%S+08")
|
||||
day_key = "2026-09-11"
|
||||
|
||||
meta = {
|
||||
"author_name": m.get("authorName", "项目成员"),
|
||||
"client_id": m.get("id"),
|
||||
}
|
||||
if m.get("attachments"):
|
||||
meta["attachments"] = m["attachments"]
|
||||
if m.get("interactiveCard"):
|
||||
meta["interactive_card"] = m["interactiveCard"]
|
||||
if m.get("phaseEvents"):
|
||||
meta["phase_events"] = m["phaseEvents"]
|
||||
|
||||
meta_json = json.dumps(meta, ensure_ascii=False).replace("'", "''")
|
||||
msg_uid = f"{uid}" if role == "user" else "NULL"
|
||||
|
||||
sql_lines.append(f"""
|
||||
INSERT INTO chat_messages (session_id, user_id, role, content, intent, branch, metadata, day_key, category, created_at, content_kind, export_policy, content_revision)
|
||||
VALUES ('{sid}', {msg_uid}, '{role}', '{content}', '{intent}', '', '{meta_json}'::jsonb, '{day_key}', '{category}', '{time_str}', 'text', 'full', 1);
|
||||
""")
|
||||
|
||||
# 4. 初始化这 30 个 session 的已读位点至最新消息
|
||||
for sid, uid in sess_user_map.items():
|
||||
sql_lines.append(f"""
|
||||
INSERT INTO chat_read_positions (session_id, user_id, last_read_message_id, dismissed_unread_ids, updated_at)
|
||||
SELECT '{sid}', {uid}, COALESCE(MAX(id), 0), '{{}}'::bigint[], now()
|
||||
FROM chat_messages
|
||||
WHERE session_id = '{sid}'
|
||||
ON CONFLICT (session_id, user_id) DO UPDATE SET
|
||||
last_read_message_id = EXCLUDED.last_read_message_id,
|
||||
dismissed_unread_ids = '{{}}'::bigint[],
|
||||
updated_at = now();
|
||||
""")
|
||||
|
||||
sql_lines.append("COMMIT;")
|
||||
|
||||
out_file = "deploy/postgres/migrations/2026-09-11-seed-ten-projects-chat.sql"
|
||||
with open(out_file, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(sql_lines))
|
||||
|
||||
print(f"成功生成 SQL: {out_file} (行数: {len(sql_lines)})")
|
||||
|
||||
# 执行 SQL
|
||||
print("正在向 PostgreSQL (shuimu-context-pg-dev) 执行导入...")
|
||||
cmd = [
|
||||
"docker", "exec", "-i", "shuimu-context-pg-dev",
|
||||
"psql", "-U", "app", "-d", "agent_system_dev", "-f", "-"
|
||||
]
|
||||
proc = subprocess.run(cmd, input="\n".join(sql_lines).encode("utf-8"), capture_output=True)
|
||||
if proc.returncode != 0:
|
||||
print("执行失败:", proc.stderr.decode("utf-8"))
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("成功导入数据库!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user