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

@@ -73,6 +73,7 @@ cp .env.example .env
- `SESSION_REUSE_ENABLED`:多轮对话复用上游 sessionId默认 `true`)。命中时只把最新一条 user 消息发给 Lingma命中上游 KV cache显著降低第 2 轮及以后的首 token 延迟
- `SESSION_CACHE_MAX_ENTRIES`会话缓存容量LRU默认 256
- `SESSION_CACHE_TTL_SEC`:会话缓存 TTL 秒数(默认 1800超时自动失效避免复用到已被 Lingma 回收的 session
- `LINGMA_SESSION_BUNDLE` / `LINGMA_SESSION_BUNDLE_FILE`:已登录态注入,跳过 Playwright。具体见下方"跳过自动登录"章节
### `.env` 最小必填示例
@@ -107,6 +108,49 @@ DEDICATED_DOMAIN_URL=
- `/internal/stats.pool` 按实例粒度暴露状态,`/metrics` 增加 `gateway_pool_instance_in_flight{name}` / `gateway_pool_instance_ready{name}`
- 未配置 `LINGMA_ACCOUNTS` 时自动退化为单实例模式(沿用 `LINGMA_USERNAME/LINGMA_PASSWORD`),向下兼容。
### 跳过自动登录session bundle 注入)
Playwright 登录偶尔会因为反爬虫策略失败。如果你已经有一个登录好的 Lingma
workDir本项目任意历史部署、或 VSCode 插件的 shared cache可以直接把那
份登录态导出成 "bundle" 注入到新的部署,完全跳过浏览器。
**导出**(在一个已登录的 gateway 上执行):
```bash
curl -sS -X POST \
-H "Authorization: Bearer $API_KEY" \
"http://host:port/internal/session/export" \
| jq -r '.bundle_b64' > lingma-session.b64
```
可选 `?instance=inst-0` 指定从哪个实例导出(多实例场景)。
**注入**(新部署的 `.env` 三选一):
```env
# 方式 1直接塞 base64
LINGMA_SESSION_BUNDLE=H4sIAAAA...
# 方式 2从文件读推荐避免 env 过长)
LINGMA_SESSION_BUNDLE_FILE=/secrets/lingma-session.b64
# 方式 3多账号模式每个账号独立 bundleJSON 模式)
LINGMA_ACCOUNTS=[
{"username":"u1","password":"p1","session_bundle_file":"/secrets/u1.b64"},
{"username":"u2","password":"p2","session_bundle":"H4sIAAAA..."}
]
```
**行为**
- bundle 只在目标 workDir **没有** 已有登录态(即 `cache/user` 为空或不存在)时才注入,不会覆盖活跃的登录。
- 注入成功后 Lingma 启动时直接 ready`auth_status()` 命中已登录,跳过
Playwright。
- 注入失败bundle 损坏、权限不足等)自动 fallback 到原有 Playwright 流程。
- bundle 只打包 `cache/{id,user,quota,config.json}` 四个文件,不包含
db/logs/index体积通常 < 10 KB。
- bundle 含敏感 token**按密钥保管**,不要写入公共仓库。
## 3. Docker 运行
```bash