Lock the right pane while focused, add project focus, quiet lead

This commit is contained in:
Ian Gulliver
2026-10-15 09:59:13 -07:00
parent bdd1ae48f0
commit fdd005b591
32 changed files with 576 additions and 227 deletions
+19
View File
@@ -30,6 +30,8 @@ export type Head = {
export const models = ["claude-opus-5-5", "claude-sonnet-5-5", "claude-haiku-5-5", "claude-fable-5-1"];
const quietReply = "NO_REPLY";
type Call = { name: string; target: string };
type Run = {
@@ -57,6 +59,7 @@ type Ctx = {
taskId: string | undefined;
lastMessage: HTMLElement | undefined;
turnStart: HTMLElement | undefined;
quiet: boolean;
watchReport: (el: HTMLElement, itemId: string) => void;
};
@@ -224,6 +227,7 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
unplaced: [],
lastMessage: undefined,
turnStart: undefined,
quiet: false,
root: src.root(),
taskId: src.taskId(),
watchReport: (el, itemId) => {
@@ -414,6 +418,7 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
}
stream.timer = 0;
const pinned = transcript.scrollHeight - transcript.scrollTop - transcript.clientHeight < 80;
stream.el.hidden = quietReply.startsWith(stream.text.trim());
replace(stream.el, markdown(stream.text, "text md", { taskId: ctx.taskId }));
if (pinned) {
transcript.scrollTop = transcript.scrollHeight;
@@ -478,6 +483,14 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
ctx.turnStart = undefined;
continue;
}
if (ev.kind === "turn.ended" && ctx.quiet && ctx.turnStart?.parentNode === transcript) {
const brief = ctx.turnStart.querySelector(".tool-brief")?.textContent;
const label = h("div", {}, brief && h("span", { class: "tool-name" }, "byre"), brief && " ", h("span", { class: "tool-brief" }, brief ? `${brief} · nothing to say` : "nothing to say"));
addAnchor(ev.seq, foldTurn(ctx.turnStart, label), true);
ctx.turnStart = undefined;
ctx.quiet = false;
continue;
}
put(el);
if (ev.kind === "user.message") {
ctx.turnStart = el;
@@ -842,6 +855,7 @@ function renderEvent(ev: ByreEvent, ctx: Ctx): HTMLElement | null {
switch (ev.kind) {
case "user.message":
ctx.lastMessage = undefined;
ctx.quiet = false;
if (ev.actor === "byre") {
const text = String(p["text"]);
const first = text.split("\n")[0] ?? "";
@@ -862,6 +876,11 @@ function renderEvent(ev: ByreEvent, ctx: Ctx): HTMLElement | null {
);
case "agent.message":
if (String(p["text"]).trim() === quietReply) {
ctx.quiet = true;
return null;
}
ctx.quiet = false;
ctx.lastMessage = h("div", { class: "msg agent" }, markdown(String(p["text"]), "text md", md));
return ctx.lastMessage;