This commit is contained in:
Ian Gulliver
2026-10-16 09:51:32 -07:00
parent 59c2b2cb9c
commit 48ef2d6bb5
12 changed files with 343 additions and 192 deletions
+8 -3
View File
@@ -211,10 +211,11 @@ export function taskPane() {
}
function trackPaneFocus(pane) {
let focused = false;
let drafting = false;
let inside = null;
let sending = Promise.resolve();
const send = () => {
const body = { focused };
const body = { focused, drafting };
sending = sending.then(() => put("/api/me/pane-focus", { body })).catch((err) => console.error("set pane focus", err));
};
const update = () => {
@@ -225,11 +226,13 @@ function trackPaneFocus(pane) {
}
const active = document.activeElement;
const now = document.hasFocus() && pane.contains(active);
const draft = [...pane.querySelectorAll("textarea:not(.xterm-helper-textarea)")].some((t) => t.value.trim() !== "");
inside = now ? active : null;
if (now === focused) {
if (now === focused && draft === drafting) {
return;
}
focused = now;
drafting = draft;
send();
});
};
@@ -240,12 +243,14 @@ function trackPaneFocus(pane) {
});
document.addEventListener("focusin", update);
document.addEventListener("focusout", update);
document.addEventListener("input", update);
document.addEventListener("submit", update);
addEventListener("focus", update);
addEventListener("blur", update);
addEventListener("pagehide", () => {
if (focused) {
focused = false;
void put("/api/me/pane-focus", { body: { focused: false }, keepalive: true });
void put("/api/me/pane-focus", { body: { focused: false, drafting }, keepalive: true });
}
});
}
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -1
View File
@@ -96,7 +96,7 @@ export interface paths {
cookie?: never;
};
get?: never;
/** @description Records whether the human is working in the right pane. While they are, the lead agent can't move it. */
/** @description Records whether the human is working in the right pane, and whether they have unsent text there. While they are working in it, the lead agent can move it only in the cases its show tool describes. */
put: operations["setPaneFocus"];
post?: never;
delete?: never;
@@ -1198,6 +1198,8 @@ export interface components {
PaneFocus: {
/** @description True while the browser window has focus and the focused element is inside the right pane. */
focused: boolean;
/** @description True while a text box in the right pane holds unsent text. */
drafting: boolean;
};
/** @enum {string} */
TaskTab: "transcript" | "changes" | "files" | "terminal" | "inbox" | "reviews" | "project";
+8 -3
View File
@@ -238,10 +238,11 @@ export function taskPane(): HTMLElement {
function trackPaneFocus(pane: HTMLElement): void {
let focused = false;
let drafting = false;
let inside: Element | null = null;
let sending: Promise<unknown> = Promise.resolve();
const send = () => {
const body = { focused };
const body = { focused, drafting };
sending = sending.then(() => put("/api/me/pane-focus", { body })).catch((err: unknown) => console.error("set pane focus", err));
};
const update = () => {
@@ -252,11 +253,13 @@ function trackPaneFocus(pane: HTMLElement): void {
}
const active = document.activeElement;
const now = document.hasFocus() && pane.contains(active);
const draft = [...pane.querySelectorAll<HTMLTextAreaElement>("textarea:not(.xterm-helper-textarea)")].some((t) => t.value.trim() !== "");
inside = now ? active : null;
if (now === focused) {
if (now === focused && draft === drafting) {
return;
}
focused = now;
drafting = draft;
send();
});
};
@@ -267,12 +270,14 @@ function trackPaneFocus(pane: HTMLElement): void {
});
document.addEventListener("focusin", update);
document.addEventListener("focusout", update);
document.addEventListener("input", update);
document.addEventListener("submit", update);
addEventListener("focus", update);
addEventListener("blur", update);
addEventListener("pagehide", () => {
if (focused) {
focused = false;
void put("/api/me/pane-focus", { body: { focused: false }, keepalive: true });
void put("/api/me/pane-focus", { body: { focused: false, drafting }, keepalive: true });
}
});
}