feat(browser): self-heal sessions after camofox restarts (BR-3)
- Any session operation that hits 404/410 (or finds no open tab) reconciles
tabs; if none survive it re-injects the account cookies (BR-2), opens a new
tab under the same userId/sessionKey, returns to the recorded URL (site home
otherwise), marks old tabs lost and retries the operation once. Failure
returns 503 browser_reconnect_failed with the reason, with a 10s backoff.
- Restart detection: umt plugin GET /umt/instance (fallback /health fields);
a changed instance id marks every open session needsReconnect.
- POST /browser/sessions/{id}/reconnect (idempotent); session view exposes
needsReconnect and reconnect {status, trigger, at, reason, humanNotice}.
- Controller and lease are kept; reconnecting during takeover asks the human
to double-check the reloaded page.
- Web: screenshot and desktop modes show "reconnecting", auto-reconnect once,
pause polling, offer a reconnect button with the reason on failure; desktop
mode rebuilds the Selkies connection after a reconnect.
- Mock camofox restart(), tests, smoke step and runbook section 10.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
da24380870
commit
838aea3ebd
19 files changed
+977
-45
No files matched your search
@@ -5,12 +5,17 @@
|
||||
* (CAMOFOX_ACCESS_KEY,ctx.auth())之下提供:
|
||||
* POST /umt/sessions/:userId/cookies { cookies: Cookie[] } → 写入该 profile 的 BrowserContext 并触发持久化落盘
|
||||
* GET /umt/sessions/:userId/cookies?urls=a,b → 读作用于这些地址的 Cookie(活动上下文优先,否则读落盘文件)
|
||||
* GET /umt/instance → { instanceId, startedAt }:插件加载时生成,进程重启即变
|
||||
* (BR-3:app 据此发现容器重启,把会话标为需要重新连接)
|
||||
* Cookie 值只在请求/响应体里,不写日志(只记个数)。
|
||||
*/
|
||||
import { randomUUID } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import express from "express";
|
||||
import { getUserPersistencePaths } from "../../lib/persistence.js";
|
||||
|
||||
const INSTANCE = { instanceId: randomUUID(), startedAt: new Date().toISOString() };
|
||||
|
||||
const FIELDS = ["name", "value", "domain", "path", "expires", "httpOnly", "secure", "sameSite"];
|
||||
|
||||
function parseUrls(raw) {
|
||||
@@ -101,5 +106,7 @@ export async function register(app, ctx) {
|
||||
}
|
||||
});
|
||||
|
||||
log("info", "umt-cookies plugin: registered GET/POST /umt/sessions/:userId/cookies");
|
||||
app.get("/umt/instance", ctx.auth(), (_req, res) => res.json(INSTANCE));
|
||||
|
||||
log("info", "umt-cookies plugin: registered GET/POST /umt/sessions/:userId/cookies, GET /umt/instance");
|
||||
}
|
||||
Reference in new issue
Block a user