feat: session bundle import/export to skip Playwright auto-login

Adds a lightweight way to pre-seed a Lingma workDir with an existing
logged-in session:

- New module session_bundle.py packs/unpacks only the four cache files
  that make up a Lingma login (id, user, quota, config.json). Everything
  else (db, logs, index, diagnosis) stays local so bundles stay tiny
  and never leak session-specific artefacts.
- Safety: path-traversal/symlink members are rejected; size is capped;
  refuses to export from a workDir that isn't actually logged in;
  sensitive cache/user is chmod'd 0600 on restore.
- LingmaAccount gains optional session_bundle_b64 / session_bundle_file;
  LINGMA_SESSION_BUNDLE[_FILE] env provide the singleton fallback.
  Credentials become optional when a bundle is supplied.
- LingmaPool.start() restores the bundle into each instance workDir
  only if it isn't already logged in, so persistent volumes aren't
  clobbered and a corrupt bundle falls back to Playwright gracefully.
- POST /internal/session/export returns the bundle as base64; ?instance=
  selects a specific pool instance. Requires an authed, already-logged-in
  instance to prevent exporting empties.
- README + .env.example document the end-to-end flow.

Made-with: Cursor
This commit is contained in:
GitHub Actions
2026-04-18 09:39:58 +08:00
parent ba865f3be0
commit 4e08d1af36
6 changed files with 386 additions and 3 deletions

View File

@@ -68,6 +68,23 @@ LINGMA_ACCOUNTS=
# 实例数量:默认等于 LINGMA_ACCOUNTS 数;显式指定时账号不足会循环复用并打 warning
LINGMA_INSTANCE_COUNT=
# ==== 登录态注入:跳过 Playwright 自动登录 ====
# 方式 1base64 字符串,内容 = tar.gz(workDir/cache/{id,user,quota,config.json})
# 通过 `POST /internal/session/export` 从另一个已登录实例导出得到。
# 配了这个就可以不填 LINGMA_USERNAME / LINGMA_PASSWORD。
# LINGMA_SESSION_BUNDLE=
# 方式 2指向宿主机上的 bundle 文件路径(文件内容即 base64 字符串)
# LINGMA_SESSION_BUNDLE_FILE=/secrets/lingma-session.b64
# 多账号时走 JSON 模式,每个账号可以独立带 session_bundle
# LINGMA_ACCOUNTS=[
# {"username":"u1","password":"p1","session_bundle":"H4sI..."},
# {"username":"u2","password":"p2","session_bundle_file":"/secrets/u2.b64"}
# ]
# 注意:一旦 workDir 里已经有登录态cache/user 非空bundle 会被跳过,
# 你手动登录的 / 旧容器的登录态不会被覆盖。
# ==== 会话复用(多轮对话命中上游 KV cache减少首 token 延迟) ====
# 开关(默认开)
SESSION_REUSE_ENABLED=true