aboutsummaryrefslogtreecommitdiff
path: root/src/index.ts
diff options
context:
space:
mode:
authorAman Kumar <145339995+amankumarsingh77@users.noreply.github.com>2026-07-22 00:59:58 +0530
committerGitHub <noreply@github.com>2026-07-22 00:59:58 +0530
commitfe00d3361dece3d35f788d3eeb1c750eedbf6294 (patch)
treea51b8ffe3cddb1aa8d457784f71cc1b2b0b61d56 /src/index.ts
parent7de0beaf2cf713afc50c573e941fa279ec6df9d9 (diff)
feat: add forms domain and durable window binding (v0.9.0) (#14)
- Add forms domain with a universal field setter that auto-detects element type and fires framework-compatible input events (React native-setter trick) - Add window-binding helper to capture and bind the real Chrome windowId as the session's durable window identity on every new-window code path - Wire supporting changes across CDP session/ownership, client, navigate, isolated-tab, prompt, and state - Add manual tests for forms and window binding - Bump version 0.8.3 -> 0.9.0 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'src/index.ts')
-rw-r--r--src/index.ts17
1 files changed, 14 insertions, 3 deletions
diff --git a/src/index.ts b/src/index.ts
index d5f3435..7109ea0 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -109,9 +109,10 @@ export default function browserHarnessExtension(pi: ExtensionAPI): void {
if (!client) {
const transport = createDaemonTransport(state.namespace);
- const initialOwnership: { ownedTargetIds?: ReadonlyArray<string>; harnessWindowTargetId?: string } = {};
+ const initialOwnership: { ownedTargetIds?: ReadonlyArray<string>; harnessWindowTargetId?: string; harnessWindowId?: number } = {};
if (state.ownedTargetIds !== undefined) initialOwnership.ownedTargetIds = state.ownedTargetIds;
if (state.harnessWindowTargetId !== undefined) initialOwnership.harnessWindowTargetId = state.harnessWindowTargetId;
+ if (state.harnessWindowId !== undefined) initialOwnership.harnessWindowId = state.harnessWindowId;
client = createBrowserClient({
namespace: state.namespace,
@@ -124,6 +125,9 @@ export default function browserHarnessExtension(pi: ExtensionAPI): void {
...(snap.harnessWindowTargetId !== undefined
? { harnessWindowTargetId: snap.harnessWindowTargetId }
: {}),
+ ...(snap.harnessWindowId !== undefined
+ ? { harnessWindowId: snap.harnessWindowId }
+ : {}),
};
// Ownership changes can fire from CDP events at any time,
// including after session replacement when pi's ctx is stale.
@@ -147,20 +151,27 @@ export default function browserHarnessExtension(pi: ExtensionAPI): void {
});
pi.on("session_shutdown", async () => {
- persistState(pi, state);
if (client) {
try {
// Detach from the page target (removes the "Chrome is being controlled"
// banner) but keep the transport alive for the next session.
await client.detach();
+ // Close every tab this session opened so no stale harness tabs linger
+ // in the user's browser between sessions. This also clears the persisted
+ // ownership + window binding via onOwnershipChange, so the next session
+ // starts with a fresh dedicated window rather than reattaching to leftovers.
+ await client.closeOwnedTabs();
} catch (e) {
- console.warn("[pi-browser-harness] client.detach() failed during shutdown:", e);
+ console.warn("[pi-browser-harness] browser teardown failed during shutdown:", e);
}
// ponytail: keep the transport alive across sessions.
// Do NOT call client.stop() or null out client — the daemon connection
// persists and eliminates the per-session "Allow Remote Debugging" prompt.
// Only Chrome restart or daemon death triggers a new prompt.
}
+ // Persist last — closeOwnedTabs mutates `state` through onOwnershipChange,
+ // so this captures the cleared ownership set.
+ persistState(pi, state);
await cleanupTempDirs();
});