Replace browser popups with in-page dialogs; focus new-task prompt

This commit is contained in:
Ian Gulliver
2026-10-14 22:42:46 -07:00
parent 1dc09c77e0
commit 4ffdc1e517
32 changed files with 270 additions and 195 deletions
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AA2CA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACZ;IAArB,YAAqB,MAAc,EAAE,OAAe;QAClD,KAAK,CAAC,OAAO,CAAC,CAAC;QADI,WAAM,GAAN,MAAM,CAAQ;IAEnC,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAS,EACT,IAAO,EACP,OAA0B,EAAE;IAE5B,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;IAChE,IAAI,GAAG,GAAW,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,GAAW,EAAE,EAAE;QAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,QAAQ,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC,EAAE,CAAC;QACzF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACnB,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;IAC3D,IAAI,IAAI,CAAC,IAAI,YAAY,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,0BAA0B,EAAE,CAAC;QAChF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,OAAO,SAA6B,CAAC;IACvC,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAG,IAAyB,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAwB,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,CAA6B,IAAO,EAAE,IAA4B,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACrH,MAAM,CAAC,MAAM,IAAI,GAAG,CAA8B,IAAO,EAAE,IAA6B,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACzH,MAAM,CAAC,MAAM,GAAG,GAAG,CAA6B,IAAO,EAAE,IAA4B,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACrH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAgC,IAAO,EAAE,IAA+B,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAE9H,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,YAAY,GAAG,KAAK,CAAC;AAE3B,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,OAAgC,EAAE,OAAqC;IAC9G,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,MAA+B,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,IAAI,WAAW,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,GAAG,CAAC,CAAC;QACX,CAAC,CAAC,MAAM,GAAG,GAAG,EAAE;YACd,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC;QACF,CAAC,CAAC,OAAO,GAAG,GAAG,EAAE;YACf,OAAO,CAAC,KAAK,CAAC,CAAC;YACf,IAAI,CAAC,CAAC,UAAU,KAAK,WAAW,CAAC,MAAM,EAAE,CAAC;gBACxC,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;QACF,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YAC9B,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,SAAS,GAAG,CAAC,GAAyB,EAAE,EAAE;YAC1C,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACnB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAc,CAAC;YAC7C,IAAI,EAAE,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC;gBAClB,IAAI,GAAG,EAAE,CAAC,GAAG,CAAC;YAChB,CAAC;YACD,OAAO,CAAC,EAAE,CAAC,CAAC;QACd,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,YAAY,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,CAAC;QACf,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC1B,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,GAAG,EAAE;QACjD,IAAI,QAAQ,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;YAC3C,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC"}
+2 -2
View File
@@ -1,5 +1,5 @@
import { get, put, subscribe } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { mountNavbar } from "./navbar.js";
import { Pane } from "./panes.js";
import { handleEvent, loadInbox, loadMe, loadProjects, notify, on, selectTask, state } from "./state.js";
@@ -21,7 +21,7 @@ function identityBanner(root) {
render();
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
root.hidden = false;
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
+23
View File
@@ -42,4 +42,27 @@ export function ago(iso) {
export function errorText(err) {
return err instanceof Error ? err.message : String(err);
}
function modal(text, buttons) {
const actions = buttons.map((b) => h("button", { type: "submit", value: b.value, class: b.class ?? "" }, b.label));
const dialog = h("dialog", { class: "modal" }, h("form", { method: "dialog" }, h("p", { class: "modal-text" }, text), h("div", { class: "modal-actions" }, ...actions)));
document.body.append(dialog);
return new Promise((resolve) => {
dialog.onclose = () => {
dialog.remove();
resolve(dialog.returnValue);
};
dialog.showModal();
actions.at(-1)?.focus();
});
}
export async function showAlert(text) {
await modal(text, [{ label: "OK", value: "ok", class: "primary" }]);
}
export async function showConfirm(text, action, danger = false) {
const value = await modal(text, [
{ label: "Cancel", value: "cancel" },
{ label: action, value: "ok", class: danger ? "danger-primary" : "primary" },
]);
return value === "ok";
}
//# sourceMappingURL=dom.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,CAAC,CAAwC,GAAM,EAAE,QAAkB,EAAE,EAAE,GAAG,QAAiB;IACzG,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAEzD,IAAI,SAAS,EAAE,CAAC;QACd,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC;IAC3B,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;QACtD,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC1B,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAExB,MAAM,CAAC,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EAAQ,EAAE,GAAG,QAAiB;IACnD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YAC7D,SAAS;QACX,CAAC;QACD,EAAE,CAAC,WAAW,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAW,EAAE,GAAG,QAAiB;IACvD,EAAE,CAAC,eAAe,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,GAAW;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAClE,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACjB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;QACnB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC;IAC5C,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;QACpB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC9C,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC"}
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"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"}
+3 -3
View File
@@ -1,6 +1,6 @@
import { post } from "./api.js";
import { mountChanges } from "./changes.js";
import { ago, errorText, h, replace } from "./dom.js";
import { ago, errorText, h, replace, showAlert } from "./dom.js";
import { inlineMarkdown, markdown } from "./markdown.js";
import { findTask, onEach, state } from "./state.js";
const drafts = new Map();
@@ -50,7 +50,7 @@ export function mountInbox(root) {
}
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
button.disabled = false;
render();
@@ -142,7 +142,7 @@ function card(item, changed) {
await post("/api/inbox/responses", { body: { responses: [{ item_id: item.id, type: "dismiss" }] } });
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
ok.disabled = false;
}
};
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1,5 +1,5 @@
import { post } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { openTranscript } from "./panes.js";
import { activeTasks, currentSession, findTask, onEach, state } from "./state.js";
export function mountNavbar(root, show) {
@@ -28,7 +28,7 @@ export function mountNavbar(root, show) {
replace(root, h("a", { href: "#/", class: "brand" }, "byre"), crumb, h("span", { class: "spacer" }), inbox, admin, connLabel, conn, me);
render();
addEventListener("keydown", (e) => {
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
if (e.key === "k" && (e.metaKey || e.ctrlKey) && !document.querySelector("dialog[open]")) {
e.preventDefault();
openSwitcher();
}
@@ -72,7 +72,7 @@ function openSwitcher() {
go(task.id);
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
const render = () => {
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1,5 +1,5 @@
import { del, get, post, put } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { on, state } from "./state.js";
const kinds = [
{ key: "blocking_questions", label: "Blocking questions" },
@@ -24,7 +24,7 @@ export function mountSettings(root) {
state.me = await put("/api/me/notifications", { body: { ...me.notification_prefs, [key]: box.checked } });
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
renderPrefs();
};
@@ -57,7 +57,7 @@ export function mountSettings(root) {
}
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
await renderDevice();
};
+1 -1
View File
File diff suppressed because one or more lines are too long
+25 -23
View File
@@ -1,5 +1,5 @@
import { get, post } from "./api.js";
import { ago, errorText, h, replace } from "./dom.js";
import { post } from "./api.js";
import { ago, errorText, h, replace, showAlert, showConfirm } from "./dom.js";
import { markdown } from "./markdown.js";
import { currentSession, findTask, onEach, state } from "./state.js";
const models = ["claude-opus-5-5", "claude-sonnet-5-5", "claude-haiku-5-5", "claude-fable-5-1"];
@@ -93,7 +93,7 @@ export function mountTranscript(root) {
const target = state.projects.find((p) => p.id === task.project_id)?.default_branch ?? "the default branch";
const busy = sess?.state === "running" || sess?.state === "queued";
const merge = h("button", { disabled: busy, title: `The agent merges ${target} in, then byre squashes into one commit on ${target}; nothing is pushed` }, "Merge");
merge.onclick = () => confirmChanges(task, (u) => `Merge "${task.title}" into ${target}? The agent first merges ${target} in and resolves any conflicts; when that turn ends, ${changesText(u)} become one commit on ${target} titled "${task.merge_title}", and the task closes. Nothing is pushed.`, async () => {
merge.onclick = () => confirmThen(`Merge "${task.title}" into ${target}?`, "Merge", false, async () => {
await post("/api/tasks/{taskId}/merge", { path: { taskId: task.id } });
});
const mergeIn = h("button", { disabled: busy, title: `Ask the agent to merge ${target} into this branch and resolve any conflicts` }, `Merge ${target} in`);
@@ -103,18 +103,19 @@ export function mountTranscript(root) {
await post("/api/tasks/{taskId}/merge-in", { path: { taskId: task.id } });
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
mergeIn.disabled = false;
}
};
const discard = h("button", { class: "danger", disabled: busy, title: "Delete the worktree and branch without merging" }, "Discard");
discard.onclick = () => confirmChanges(task, (u) => `Discard "${task.title}"? ${changesText(u)} that aren't on ${target} will be deleted. This can't be undone.`, async () => {
discard.onclick = () => confirmThen(`Discard "${task.title}"?`, "Discard", true, async () => {
await post("/api/tasks/{taskId}/discard", { path: { taskId: task.id } });
location.hash = "#/";
});
replace(head, h("div", { class: "head-actions session-actions" }, sess && contextMeter(context.get(sess.id)), sess && compactButton(sess.id, sess.state), mergeIn), h("div", { class: "head-actions" }, merge, discard));
};
let composerModel = "";
let focusStart = false;
const renderComposer = () => {
const task = state.selectedTaskId ? findTask(state.selectedTaskId) : undefined;
if (!task) {
@@ -123,9 +124,15 @@ export function mountTranscript(root) {
}
const sess = currentSession(task.id);
if (!sess || sess.state === "completed") {
replace(composer, startForm(task.id));
const form = startForm(task.id);
replace(composer, form);
if (focusStart && !sess) {
form.querySelector("textarea")?.focus();
}
focusStart = false;
return;
}
focusStart = false;
composerModel = sess.model || context.get(sess.id)?.model || "";
replace(composer, messageForm(task.id, sess.id, sess.state, composerModel));
};
@@ -248,6 +255,7 @@ export function mountTranscript(root) {
dropStream();
ctx = newCtx();
context = new Map();
focusStart = true;
renderHead();
if (!state.selectedTaskId) {
renderComposer();
@@ -327,11 +335,11 @@ function imageTray(form, input, key) {
const added = [];
for (const f of files) {
if (!imageTypes.includes(f.type)) {
alert(`${f.name || "That file"} isn't a PNG, JPEG, GIF or WebP image.`);
void showAlert(`${f.name || "That file"} isn't a PNG, JPEG, GIF or WebP image.`);
continue;
}
if (f.size > maxImageBytes) {
alert(`${f.name || "That image"} is over ${maxImageBytes >> 20} MiB.`);
void showAlert(`${f.name || "That image"} is over ${maxImageBytes >> 20} MiB.`);
continue;
}
added.push({ file: f, url: URL.createObjectURL(f) });
@@ -424,7 +432,7 @@ function startForm(taskId) {
composerDrafts.set(`start:${taskId}`, value);
prompt.value = value;
tray.restore(imgs);
alert(errorText(err));
void showAlert(errorText(err));
}
};
submitOnEnter(prompt, form);
@@ -453,7 +461,7 @@ function messageForm(taskId, sessionId, sessionState, currentModel) {
await post("/api/sessions/{sessionId}/interrupt", { path: { sessionId } });
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
const model = modelSelect(`message:${sessionId}`, currentModel);
@@ -482,7 +490,7 @@ function messageForm(taskId, sessionId, sessionState, currentModel) {
composerDrafts.set(`message:${taskId}`, value);
text.value = value;
tray.restore(imgs);
alert(errorText(err));
void showAlert(errorText(err));
}
};
submitOnEnter(text, form);
@@ -504,7 +512,7 @@ function compactButton(sessionId, sessionState) {
await post("/api/sessions/{sessionId}/compact", { path: { sessionId } });
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
b.disabled = false;
}
};
@@ -622,23 +630,17 @@ function messageImages(ids) {
return h("a", { href: src, target: "_blank", rel: "noopener" }, h("img", { src, alt: "attached image", loading: "lazy" }));
}));
}
async function confirmChanges(task, prompt, act) {
async function confirmThen(question, action, danger, act) {
if (!(await showConfirm(question, action, danger))) {
return;
}
try {
const u = await get("/api/tasks/{taskId}/unmerged", { path: { taskId: task.id } });
if (!confirm(prompt(u))) {
return;
}
await act();
}
catch (err) {
alert(errorText(err));
await showAlert(errorText(err));
}
}
function changesText(u) {
const plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
const uncommitted = u.uncommitted > 0 ? `, ${u.uncommitted} uncommitted` : "";
return `${plural(u.commits, "commit")} and ${plural(u.files, "changed file")} (+${u.insertions} −${u.deletions}${uncommitted})`;
}
function toolBrief(input, root) {
if (typeof input !== "object" || input === null) {
return "";
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1,5 +1,5 @@
import { post } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { openTranscript } from "./panes.js";
import { currentSession, onEach, state } from "./state.js";
export function mountTasks(root) {
@@ -26,7 +26,7 @@ function newTaskForm(projectId) {
location.hash = `#/task/${task.id}`;
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
return form;
@@ -42,7 +42,7 @@ function newProjectForm() {
form.reset();
}
catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
return h("details", { class: "add-project", open: state.projects.length === 0 }, h("summary", {}, "Add project"), form);
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,UAAU,UAAU,CAAC,IAAiB;IAC1C,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAC7H,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IACpF,MAAM,EAAE,CAAC;IACT,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,YAAY,CAAC,OAAgB;IACpC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAEvF,OAAO,CAAC,CACN,SAAS,EACT,EAAE,KAAK,EAAE,SAAS,EAAE,EACpB,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,EAC/E,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,WAAW,EAAE,EACtB,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACpB,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;QAC5E,OAAO,CAAC,CACN,IAAI,EACJ,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,EAC7D,CAAC,CACC,GAAG,EACH,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,EACtD,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,IAAI,EAAE,KAAK,IAAI,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,YAAY,EAAE,CAAC,EACxF,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAC9C,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,KAAK,IAAI,UAAU,CAAC,EAC7D,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,CAAC,CAClD,CACF,CAAC;IACJ,CAAC,CAAC,EACF,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,kBAAkB,CAAC,CAC1E,EACD,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CACxB,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,SAAiB;IACpC,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,gBAAgB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnG,IAAI,CAAC,QAAQ,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,iCAAiC,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAClH,QAAQ,CAAC,IAAI,GAAG,UAAU,IAAI,CAAC,EAAE,EAAE,CAAC;QACtC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,cAAc;IACrB,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,yBAAyB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;IAC5G,IAAI,CAAC,QAAQ,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACnF,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;IACF,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1H,CAAC"}
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"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"}
-1
View File
@@ -4,7 +4,6 @@ export type Schemas = components["schemas"];
export type User = Schemas["User"];
export type Project = Schemas["Project"];
export type Task = Schemas["Task"];
export type Unmerged = Schemas["Unmerged"];
export type AgentSession = Schemas["AgentSession"];
export type InboxItem = Schemas["InboxItem"];
export type InboxResponse = Schemas["InboxResponse"];
+2 -2
View File
@@ -1,5 +1,5 @@
import { get, put, subscribe } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { mountNavbar } from "./navbar.js";
import { Pane } from "./panes.js";
import { handleEvent, loadInbox, loadMe, loadProjects, notify, on, selectTask, state } from "./state.js";
@@ -21,7 +21,7 @@ function identityBanner(root: HTMLElement): void {
state.me = await put("/api/me", { body: { git_name: name.value, git_email: email.value } });
render();
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
root.hidden = false;
+26
View File
@@ -56,3 +56,29 @@ export function ago(iso: string): string {
export function errorText(err: unknown): string {
return err instanceof Error ? err.message : String(err);
}
function modal(text: string, buttons: { label: string; value: string; class?: string }[]): Promise<string> {
const actions = buttons.map((b) => h("button", { type: "submit", value: b.value, class: b.class ?? "" }, b.label));
const dialog = h("dialog", { class: "modal" }, h("form", { method: "dialog" }, h("p", { class: "modal-text" }, text), h("div", { class: "modal-actions" }, ...actions)));
document.body.append(dialog);
return new Promise((resolve) => {
dialog.onclose = () => {
dialog.remove();
resolve(dialog.returnValue);
};
dialog.showModal();
actions.at(-1)?.focus();
});
}
export async function showAlert(text: string): Promise<void> {
await modal(text, [{ label: "OK", value: "ok", class: "primary" }]);
}
export async function showConfirm(text: string, action: string, danger = false): Promise<boolean> {
const value = await modal(text, [
{ label: "Cancel", value: "cancel" },
{ label: action, value: "ok", class: danger ? "danger-primary" : "primary" },
]);
return value === "ok";
}
+3 -3
View File
@@ -1,6 +1,6 @@
import { post, type Attachment, type InboxItem, type InboxResponseCreate } from "./api.js";
import { mountChanges } from "./changes.js";
import { ago, errorText, h, replace } from "./dom.js";
import { ago, errorText, h, replace, showAlert } from "./dom.js";
import { inlineMarkdown, markdown } from "./markdown.js";
import { findTask, onEach, state } from "./state.js";
@@ -57,7 +57,7 @@ export function mountInbox(root: HTMLElement): () => void {
modes.delete(d.item_id);
}
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
button.disabled = false;
render();
@@ -180,7 +180,7 @@ function card(item: InboxItem, changed: () => void): HTMLElement {
try {
await post("/api/inbox/responses", { body: { responses: [{ item_id: item.id, type: "dismiss" }] } });
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
ok.disabled = false;
}
};
+3 -3
View File
@@ -1,5 +1,5 @@
import { post } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { openTranscript, type View } from "./panes.js";
import { activeTasks, currentSession, findTask, onEach, state } from "./state.js";
@@ -37,7 +37,7 @@ export function mountNavbar(root: HTMLElement, show: (view: View) => void): void
render();
addEventListener("keydown", (e) => {
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
if (e.key === "k" && (e.metaKey || e.ctrlKey) && !document.querySelector("dialog[open]")) {
e.preventDefault();
openSwitcher();
}
@@ -85,7 +85,7 @@ function openSwitcher(): void {
const task = await post("/api/projects/{projectId}/tasks", { path: { projectId }, body: { title } });
go(task.id);
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
+3 -3
View File
@@ -1,5 +1,5 @@
import { del, get, post, put, type NotificationPrefs } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { on, state } from "./state.js";
const kinds: { key: keyof NotificationPrefs; label: string }[] = [
@@ -29,7 +29,7 @@ export function mountSettings(root: HTMLElement): () => void {
try {
state.me = await put("/api/me/notifications", { body: { ...me.notification_prefs, [key]: box.checked } });
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
renderPrefs();
};
@@ -63,7 +63,7 @@ export function mountSettings(root: HTMLElement): () => void {
await enable(status.reg);
}
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
await renderDevice();
};
+27 -31
View File
@@ -1,5 +1,5 @@
import { get, post, type ByreEvent, type Task, type Unmerged } from "./api.js";
import { ago, errorText, h, replace } from "./dom.js";
import { post, type ByreEvent } from "./api.js";
import { ago, errorText, h, replace, showAlert, showConfirm } from "./dom.js";
import { markdown } from "./markdown.js";
import { currentSession, findTask, onEach, state } from "./state.js";
@@ -122,27 +122,22 @@ export function mountTranscript(root: HTMLElement): () => void {
"Merge",
);
merge.onclick = () =>
confirmChanges(
task,
(u) =>
`Merge "${task.title}" into ${target}? The agent first merges ${target} in and resolves any conflicts; when that turn ends, ${changesText(u)} become one commit on ${target} titled "${task.merge_title}", and the task closes. Nothing is pushed.`,
async () => {
await post("/api/tasks/{taskId}/merge", { path: { taskId: task.id } });
},
);
confirmThen(`Merge "${task.title}" into ${target}?`, "Merge", false, async () => {
await post("/api/tasks/{taskId}/merge", { path: { taskId: task.id } });
});
const mergeIn = h("button", { disabled: busy, title: `Ask the agent to merge ${target} into this branch and resolve any conflicts` }, `Merge ${target} in`);
mergeIn.onclick = async () => {
mergeIn.disabled = true;
try {
await post("/api/tasks/{taskId}/merge-in", { path: { taskId: task.id } });
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
mergeIn.disabled = false;
}
};
const discard = h("button", { class: "danger", disabled: busy, title: "Delete the worktree and branch without merging" }, "Discard");
discard.onclick = () =>
confirmChanges(task, (u) => `Discard "${task.title}"? ${changesText(u)} that aren't on ${target} will be deleted. This can't be undone.`, async () => {
confirmThen(`Discard "${task.title}"?`, "Discard", true, async () => {
await post("/api/tasks/{taskId}/discard", { path: { taskId: task.id } });
location.hash = "#/";
});
@@ -154,6 +149,7 @@ export function mountTranscript(root: HTMLElement): () => void {
};
let composerModel = "";
let focusStart = false;
const renderComposer = () => {
const task = state.selectedTaskId ? findTask(state.selectedTaskId) : undefined;
if (!task) {
@@ -162,9 +158,15 @@ export function mountTranscript(root: HTMLElement): () => void {
}
const sess = currentSession(task.id);
if (!sess || sess.state === "completed") {
replace(composer, startForm(task.id));
const form = startForm(task.id);
replace(composer, form);
if (focusStart && !sess) {
form.querySelector("textarea")?.focus();
}
focusStart = false;
return;
}
focusStart = false;
composerModel = sess.model || context.get(sess.id)?.model || "";
replace(composer, messageForm(task.id, sess.id, sess.state, composerModel));
};
@@ -292,6 +294,7 @@ export function mountTranscript(root: HTMLElement): () => void {
dropStream();
ctx = newCtx();
context = new Map();
focusStart = true;
renderHead();
if (!state.selectedTaskId) {
renderComposer();
@@ -381,11 +384,11 @@ function imageTray(form: HTMLFormElement, input: HTMLTextAreaElement, key: strin
const added: PendingImage[] = [];
for (const f of files) {
if (!imageTypes.includes(f.type)) {
alert(`${f.name || "That file"} isn't a PNG, JPEG, GIF or WebP image.`);
void showAlert(`${f.name || "That file"} isn't a PNG, JPEG, GIF or WebP image.`);
continue;
}
if (f.size > maxImageBytes) {
alert(`${f.name || "That image"} is over ${maxImageBytes >> 20} MiB.`);
void showAlert(`${f.name || "That image"} is over ${maxImageBytes >> 20} MiB.`);
continue;
}
added.push({ file: f, url: URL.createObjectURL(f) });
@@ -482,7 +485,7 @@ function startForm(taskId: string): HTMLElement {
composerDrafts.set(`start:${taskId}`, value);
prompt.value = value;
tray.restore(imgs);
alert(errorText(err));
void showAlert(errorText(err));
}
};
submitOnEnter(prompt, form);
@@ -517,7 +520,7 @@ function messageForm(taskId: string, sessionId: string, sessionState: string, cu
try {
await post("/api/sessions/{sessionId}/interrupt", { path: { sessionId } });
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
@@ -546,7 +549,7 @@ function messageForm(taskId: string, sessionId: string, sessionState: string, cu
composerDrafts.set(`message:${taskId}`, value);
text.value = value;
tray.restore(imgs);
alert(errorText(err));
void showAlert(errorText(err));
}
};
submitOnEnter(text, form);
@@ -573,7 +576,7 @@ function compactButton(sessionId: string, sessionState: string): HTMLElement {
try {
await post("/api/sessions/{sessionId}/compact", { path: { sessionId } });
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
b.disabled = false;
}
};
@@ -727,24 +730,17 @@ function messageImages(ids: unknown): HTMLElement | null {
);
}
async function confirmChanges(task: Task, prompt: (u: Unmerged) => string, act: () => Promise<void>) {
async function confirmThen(question: string, action: string, danger: boolean, act: () => Promise<void>) {
if (!(await showConfirm(question, action, danger))) {
return;
}
try {
const u = await get("/api/tasks/{taskId}/unmerged", { path: { taskId: task.id } });
if (!confirm(prompt(u))) {
return;
}
await act();
} catch (err) {
alert(errorText(err));
await showAlert(errorText(err));
}
}
function changesText(u: Unmerged): string {
const plural = (n: number, word: string) => `${n} ${word}${n === 1 ? "" : "s"}`;
const uncommitted = u.uncommitted > 0 ? `, ${u.uncommitted} uncommitted` : "";
return `${plural(u.commits, "commit")} and ${plural(u.files, "changed file")} (+${u.insertions} −${u.deletions}${uncommitted})`;
}
function toolBrief(input: unknown, root: string): string {
if (typeof input !== "object" || input === null) {
return "";
+3 -3
View File
@@ -1,5 +1,5 @@
import { post, type Project } from "./api.js";
import { errorText, h, replace } from "./dom.js";
import { errorText, h, replace, showAlert } from "./dom.js";
import { openTranscript } from "./panes.js";
import { currentSession, onEach, state } from "./state.js";
@@ -51,7 +51,7 @@ function newTaskForm(projectId: string): HTMLElement {
const task = await post("/api/projects/{projectId}/tasks", { path: { projectId }, body: { title: title.value } });
location.hash = `#/task/${task.id}`;
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
return form;
@@ -67,7 +67,7 @@ function newProjectForm(): HTMLElement {
await post("/api/projects", { body: { name: name.value, repo_path: path.value } });
form.reset();
} catch (err) {
alert(errorText(err));
void showAlert(errorText(err));
}
};
return h("details", { class: "add-project", open: state.projects.length === 0 }, h("summary", {}, "Add project"), form);
+33
View File
@@ -1198,6 +1198,39 @@ pre.diff .meta {
margin: 0;
}
.modal {
width: min(520px, 90vw);
padding: 16px;
color: var(--text);
background: var(--raised);
border: 1px solid var(--border);
border-radius: 10px;
box-shadow: var(--shadow);
}
.modal::backdrop {
background: rgb(0 0 0 / 0.35);
}
.modal-text {
margin: 0 0 16px;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.modal-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
}
button.danger-primary {
background: var(--danger);
border-color: var(--danger);
color: var(--bg);
font-weight: 700;
}
.switcher-backdrop {
position: fixed;
inset: 0;