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
@@ -354,7 +354,7 @@ describe.skipIf(!hasPg)("E14 视觉自动化闭环", () => {
|
||||
for (const l of ledger) expect((l.output as Any).modelImage).toBeNull();
|
||||
}, 90_000);
|
||||
|
||||
it("多进程:api 重开被回收的标签页后 worker 换到新标签页;api 关闭会话后 worker 能重新打开", async () => {
|
||||
it("多进程:api 自愈重开被回收的标签页后 worker 换到新标签页;api 关闭会话后 worker 能重新打开", async () => {
|
||||
await open(ids.site, ids.provider, `${ORIGIN}/torrents.php`);
|
||||
const worker = new BrowserService(e.booted.ctx, svc.opts);
|
||||
const auto = { kind: "automation", holder: "agent:e14" } as const;
|
||||
@@ -362,10 +362,8 @@ describe.skipIf(!hasPg)("E14 视觉自动化闭环", () => {
|
||||
await snap(worker);
|
||||
const old = (await svc.view(sid)).currentTabId!;
|
||||
mock.dropTab(old);
|
||||
await expect(snap(svc)).rejects.toThrow(/回收/);
|
||||
await svc.run(sid, auto, (p, _ref, x) =>
|
||||
p.openTab(sid, { url: `${ORIGIN}/torrents.php`, budget: x.budget, as: "automation" }),
|
||||
);
|
||||
// BR-3:api 发现标签页被回收 → 同一会话新开标签页回到原地址并重试
|
||||
await expect(snap(svc)).resolves.toMatchObject({ url: expect.stringContaining("/torrents.php") });
|
||||
expect((await svc.view(sid)).currentTabId).not.toBe(old);
|
||||
await expect(snap(worker)).resolves.toMatchObject({ url: expect.stringContaining("/torrents.php") });
|
||||
// api 关闭会话后,worker 能按站点重新打开(不被内存里的旧会话挡住)
|
||||
|
||||
Reference in new issue
Block a user