Merge branch 'hh2'

# Conflicts:
#	apps/server/src/modules/browser/service.ts
#	apps/web/app/components/browser/desktop-view.tsx
#	apps/web/app/components/browser/site-origin-view.tsx
#	packages/contracts/src/browser.ts
This commit is contained in:
root committed 2026-09-29 17:43:00 +08:00
commit f41cd96fee
33 files changed
+1919 -302

No files matched your search

@@ -96,7 +96,10 @@ describe.skipIf(!up)("e2e:登录失效 → 人工接管 → 交还 → Agent 重
const fresh = await invoke("browser.snapshot", { siteId: h.siteId });
expect(fresh).toMatchObject({ controller: "automation", loginRequired: false, waitingReason: null });
expect(fresh.snapshot.text).toContain("种子列表");
expect((await h.req(`/browser/sessions/${sid}`)).body.data.needsSnapshot).toBe(false);
const afterAgent = (await h.req(`/browser/sessions/${sid}`)).body.data;
expect(afterAgent.needsSnapshot).toBe(false);
// 原站视图据此显示「Agent 正在操作」;人工动作不刷新它
expect(Date.now() - Date.parse(afterAgent.lastAutomationAt)).toBeLessThan(60_000);
const dl = await invoke("browser.download", { sessionId: sid, target: { ref: "e11" }, timeoutMs: 2_000 });
expect(dl).toMatchObject({
sourceReleaseId: h.releaseId,
+7 -1
View File
@@ -161,6 +161,8 @@ export interface RecoveryState {
/** 打开 / 重连时浏览器服务的实例标识;变了 = 浏览器服务重启过 */
instanceId?: string | null;
reconnect?: BrowserReconnectState;
/** 最近一次自动化(Agent 能力)动作成功的时间;原站视图据此区分「Agent 正在操作」与「无人操作」 */
lastAutomationAt?: string;
}
/** 同一浏览器服务的实例标识多久查一次 */
@@ -674,6 +676,7 @@ export class BrowserService {
credential: rs.credential ?? null,
needsReconnect: rs.needsReconnect === true,
reconnect: rs.reconnect ?? null,
lastAutomationAt: rs.lastAutomationAt ?? null,
};
}
@@ -1263,7 +1266,10 @@ export class BrowserService {
throw fromBrowserError(e2);
}
}
if (opts.persist !== false) await this.persist(id, loaded.provider, opts.patch?.(out) ?? {});
const automation: RecoveryState = actor.kind === "automation" ? { lastAutomationAt: this.now().toISOString() } : {};
if (opts.persist !== false)
await this.persist(id, loaded.provider, { ...(opts.patch?.(out) ?? {}), ...automation });
else if (automation.lastAutomationAt) await this.patchRecovery(await this.sessionRow(id), automation);
this.maybeSyncCookies(row);
return out;
}