fix(dsh-plugin): add PiP close button and sniff observation thumbnail media type

The Document PiP window had no close/return entry once popped out —
users could not dismiss it from inside the window. Add an onClosePip
callback and render a close button in the PiP header; clicking it
calls pipWindow.close() and the content returns to its carrier.

The observation thumbnail publisher hardcoded mediaType as "image/png"
regardless of the actual capture bytes. Reuse the existing
sniffImageMediaType helper (exported from image.ts) so the HTTP
thumbnail endpoint declares the correct Content-Type when Chromium
returns JPEG captures.

Closes #153 (Bug 2 fully; Bug 1 was fixed in #135, this covers the
remaining observation-thumbnail path).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
drakezhang
2026-09-02 16:14:24 +08:00
co-authored by Cursor
parent 49744233f7
commit 51473c01ff
6 changed files with 58 additions and 2 deletions
@@ -335,6 +335,18 @@ describe("thumbnail cadence", () => {
await waitFor(() => service.getState()[0]?.thumbnailAttachmentId === "obs-s1-1");
expect((await service.readThumbnail("obs-s1-1"))?.mediaType).toBe("image/png");
});
it("detects JPEG thumbnail bytes instead of hardcoding image/png", async () => {
const scheduler = fakeScheduler();
const runner = fakeRunner({
screenshotBytes: () => new Uint8Array([0xff, 0xd8, 0xff, 0xdb, 0x00, 0x01]),
});
const { service } = setup({ runner, scheduler });
service.addSession("s1");
scheduler.runNext();
await waitFor(() => service.getState()[0]?.thumbnailAttachmentId === "obs-s1-1");
expect((await service.readThumbnail("obs-s1-1"))?.mediaType).toBe("image/jpeg");
});
});
describe("observation traffic isolation", () => {