Offer "After review" in the Merge dialog while a review runs
This commit is contained in:
Vendored
+4
-1
@@ -62,7 +62,7 @@ export function errorText(err) {
|
||||
return err instanceof Error ? err.message : String(err);
|
||||
}
|
||||
function modal(content, buttons, anchor = null) {
|
||||
const actions = buttons.map((b) => h("button", { type: "submit", value: b.value, class: b.class ?? "", formNoValidate: b.value === "cancel" }, b.label));
|
||||
const actions = buttons.map((b) => h("button", { type: "submit", value: b.value, class: b.class ?? "", title: b.title ?? "", formNoValidate: b.value === "cancel" }, b.label));
|
||||
const body = typeof content === "string" ? [h("p", { class: "modal-text" }, content)] : content;
|
||||
const dialog = h("dialog", { class: "modal" }, h("form", { method: "dialog" }, ...body, h("div", { class: "modal-actions" }, ...actions)));
|
||||
for (const input of dialog.querySelectorAll("input")) {
|
||||
@@ -105,4 +105,7 @@ export async function showConfirm(content, action, danger = false, anchor = null
|
||||
], anchor);
|
||||
return value === "ok";
|
||||
}
|
||||
export async function showChoice(content, choices, anchor = null) {
|
||||
return modal(content, [{ label: "Cancel", value: "cancel" }, ...choices], anchor);
|
||||
}
|
||||
//# sourceMappingURL=dom.js.map
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+6
@@ -76,6 +76,9 @@ export function taskState(task) {
|
||||
if (task.merge_queued_at !== undefined) {
|
||||
return { kind: "held", label: "Merge held", title: "Waiting for the merge in progress in this project to finish" };
|
||||
}
|
||||
if (task.merge_after_review) {
|
||||
return { kind: "held", label: "Merge after review", title: "Merges when the running review finishes with no findings" };
|
||||
}
|
||||
if (open.length > 0) {
|
||||
return { kind: "error", label: "Error", title: "The agent's session failed or hit a rate limit; see the inbox" };
|
||||
}
|
||||
@@ -418,6 +421,9 @@ export function handleEvent(ev) {
|
||||
case "task.merge_title":
|
||||
case "task.merge_queued":
|
||||
case "task.merge_unqueued":
|
||||
case "task.merge_after_review":
|
||||
case "task.merge_after_review_ended":
|
||||
case "task.merge_after_review_cancelled":
|
||||
case "task.parent_merge_started":
|
||||
case "task.parent_merge_stopped":
|
||||
case "task.merge_started":
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+72
-14
@@ -1,5 +1,5 @@
|
||||
import { get, post } from "./api.js";
|
||||
import { ago, copyable, errorText, h, replace, showAlert, showConfirm } from "./dom.js";
|
||||
import { del, get, post } from "./api.js";
|
||||
import { ago, copyable, errorText, h, replace, showAlert, showChoice, showConfirm } from "./dom.js";
|
||||
import { markdown } from "./markdown.js";
|
||||
import { previewURL } from "./preview.js";
|
||||
import { findingCount, reviewCounts, severityCounts, unignoredFindings } from "./reviews.js";
|
||||
@@ -103,10 +103,12 @@ function taskHead(rerender) {
|
||||
? "Waiting for the parent task's agent to merge this subtask"
|
||||
: held
|
||||
? "Waiting for the merge in progress in this project to finish"
|
||||
: task.parent_task_id !== undefined
|
||||
? `Merge this subtask into its parent task's branch, or into ${target} (⌘S)`
|
||||
: `The agent merges ${target} in, then byre squashes into one commit on ${target} and pushes it to origin; held while another task in the project is merging (⌘S)`,
|
||||
}, intoParent ? "Merging into parent" : held ? "Merge held" : "Merge");
|
||||
: task.merge_after_review
|
||||
? "Merges when the running review finishes with no findings; open to merge now instead (⌘S)"
|
||||
: task.parent_task_id !== undefined
|
||||
? `Merge this subtask into its parent task's branch, or into ${target} (⌘S)`
|
||||
: `The agent merges ${target} in, then byre squashes into one commit on ${target} and pushes it to origin; held while another task in the project is merging (⌘S)`,
|
||||
}, intoParent ? "Merging into parent" : held ? "Merge held" : task.merge_after_review ? "Merge after review" : "Merge");
|
||||
merge.onclick = () => confirmMerge(task.id);
|
||||
const mergeIn = h("button", { disabled: busy, title: `Ask the agent to bring ${target} into this branch and resolve any conflicts` }, `Sync from ${target}`);
|
||||
mergeIn.onclick = async () => {
|
||||
@@ -523,6 +525,7 @@ export function mountChat(root, src, makeHead) {
|
||||
}
|
||||
}
|
||||
fillTodoLinks(transcript, models[0]);
|
||||
syncMergeAfterReview(transcript);
|
||||
pin();
|
||||
jump();
|
||||
};
|
||||
@@ -538,6 +541,7 @@ export function mountChat(root, src, makeHead) {
|
||||
syncRunning();
|
||||
fillTodoLinks(box, models[0]);
|
||||
earlier.after(box);
|
||||
syncMergeAfterReview(transcript);
|
||||
transcript.scrollTop = transcript.scrollHeight - fromBottom;
|
||||
};
|
||||
let disposed = false;
|
||||
@@ -610,7 +614,10 @@ export function mountChat(root, src, makeHead) {
|
||||
loading.remove();
|
||||
watchTop();
|
||||
}),
|
||||
onEach(["tasks", "sessions"], () => fillTodoLinks(transcript, models[0])),
|
||||
onEach(["tasks", "sessions"], () => {
|
||||
fillTodoLinks(transcript, models[0]);
|
||||
syncMergeAfterReview(transcript);
|
||||
}),
|
||||
on("jump", jump),
|
||||
];
|
||||
replace(root, h("div", { class: "transcript-view" }, head, transcript, composer));
|
||||
@@ -1085,6 +1092,27 @@ function renderEvent(ev, ctx) {
|
||||
return h("div", { class: "note" }, `${ev.actor} asked to merge; held until the merge in progress in this project is done `, when);
|
||||
case "task.merge_stopped":
|
||||
return h("div", { class: "note" }, `${ev.actor} stopped the merge for review: ${String(p["reason"])} `, when);
|
||||
case "task.merge_after_review": {
|
||||
const taskId = String(p["id"]);
|
||||
const cancel = h("button", { type: "button", class: "merge-after-review-cancel", hidden: true, title: "Withdraw this request; nothing is merged", data: { taskId } }, "Cancel");
|
||||
cancel.onclick = async () => {
|
||||
cancel.disabled = true;
|
||||
try {
|
||||
await del("/api/tasks/{taskId}/merge-after-review", { path: { taskId } });
|
||||
}
|
||||
catch (err) {
|
||||
void showAlert(errorText(err));
|
||||
}
|
||||
finally {
|
||||
cancel.disabled = false;
|
||||
}
|
||||
};
|
||||
return h("div", { class: "note" }, `${ev.actor} asked to merge once the review of snapshot #${String(p["snapshot_n"])} finishes with no findings `, when, cancel);
|
||||
}
|
||||
case "task.merge_after_review_cancelled":
|
||||
return h("div", { class: "note" }, `${ev.actor} cancelled the merge after review `, when);
|
||||
case "task.merge_after_review_dropped":
|
||||
return h("div", { class: "note" }, `didn't merge after the review: ${String(p["reason"])} `, when);
|
||||
case "preview.exposed": {
|
||||
const url = previewURL(Number(p["port"]));
|
||||
return h("div", { class: "note" }, `${ev.actor} exposed "${String(p["name"])}" at `, h("a", { href: url, target: "_blank", rel: "noopener" }, url), " ", when);
|
||||
@@ -1103,6 +1131,13 @@ function renderEvent(ev, ctx) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function syncMergeAfterReview(root) {
|
||||
const buttons = [...root.querySelectorAll(".merge-after-review-cancel")];
|
||||
const last = buttons.at(-1);
|
||||
for (const b of buttons) {
|
||||
b.hidden = b !== last || findTask(b.dataset["taskId"] ?? "")?.merge_after_review !== true;
|
||||
}
|
||||
}
|
||||
function taskLink(id) {
|
||||
const task = findTask(id);
|
||||
if (task?.status !== "active") {
|
||||
@@ -1212,11 +1247,30 @@ export async function confirmMerge(taskId) {
|
||||
};
|
||||
const watch = watchMergeWarnings(taskId, warnings, leave);
|
||||
await watch.ready;
|
||||
const anchor = document.querySelector(".merge-button");
|
||||
const merge = async (afterReview) => {
|
||||
const body = toParent ? { target: "parent" } : { merge_title: input?.value ?? title };
|
||||
try {
|
||||
await post("/api/tasks/{taskId}/merge", { path: { taskId }, body: afterReview ? { ...body, after_review: true } : body });
|
||||
}
|
||||
catch (err) {
|
||||
await showAlert(errorText(err));
|
||||
}
|
||||
};
|
||||
try {
|
||||
await confirmThen(question, "Merge", false, document.querySelector(".merge-button"), async () => {
|
||||
const body = toParent ? { target: "parent" } : { merge_title: input?.value ?? title };
|
||||
await post("/api/tasks/{taskId}/merge", { path: { taskId }, body });
|
||||
});
|
||||
if (!watch.reviewRunning()) {
|
||||
if (await showConfirm(question, "Merge", false, anchor)) {
|
||||
await merge(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const choice = await showChoice(question, [
|
||||
{ label: "Merge now", value: "now" },
|
||||
{ label: "After review", value: "after", class: "primary", title: "Merge once the running review finishes with no findings" },
|
||||
], anchor);
|
||||
if (choice === "now" || choice === "after") {
|
||||
await merge(choice === "after");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
watch.dispose();
|
||||
@@ -1225,6 +1279,7 @@ export async function confirmMerge(taskId) {
|
||||
const mergeDrafts = new Map();
|
||||
function watchMergeWarnings(taskId, list, leave) {
|
||||
let reviewItems = [];
|
||||
let running = false;
|
||||
let target = 0;
|
||||
const render = () => {
|
||||
const questions = state.inbox.filter((i) => i.task_id === taskId && i.kind === "question").length;
|
||||
@@ -1239,14 +1294,16 @@ function watchMergeWarnings(taskId, list, leave) {
|
||||
const load = async () => {
|
||||
const started = ++target;
|
||||
let items;
|
||||
let isRunning = false;
|
||||
try {
|
||||
items = await reviewWarnings(taskId, leave);
|
||||
({ items, running: isRunning } = await reviewWarnings(taskId, leave));
|
||||
}
|
||||
catch (err) {
|
||||
items = [mergeWarning("Review status unavailable", undefined, errorText(err))];
|
||||
}
|
||||
if (started === target) {
|
||||
reviewItems = items;
|
||||
running = isRunning;
|
||||
render();
|
||||
}
|
||||
};
|
||||
@@ -1261,6 +1318,7 @@ function watchMergeWarnings(taskId, list, leave) {
|
||||
];
|
||||
return {
|
||||
ready: load(),
|
||||
reviewRunning: () => running,
|
||||
dispose: () => {
|
||||
target++;
|
||||
for (const off of offs) {
|
||||
@@ -1273,7 +1331,7 @@ async function reviewWarnings(taskId, leave) {
|
||||
const [snaps, reviews] = await Promise.all([get("/api/tasks/{taskId}/snapshots", { path: { taskId } }), get("/api/tasks/{taskId}/reviews", { path: { taskId } })]);
|
||||
const latest = snaps.at(-1);
|
||||
if (!latest) {
|
||||
return [mergeWarning("These changes haven't been reviewed")];
|
||||
return { items: [mergeWarning("These changes haven't been reviewed")], running: false };
|
||||
}
|
||||
const items = [];
|
||||
const open = () => leave(() => {
|
||||
@@ -1297,7 +1355,7 @@ async function reviewWarnings(taskId, leave) {
|
||||
if (changes.files.length > 0) {
|
||||
items.push(mergeWarning("Changes since the last snapshot haven't been reviewed"));
|
||||
}
|
||||
return items;
|
||||
return { items, running: r?.state === "running" };
|
||||
}
|
||||
function mergeWarning(text, open, detail) {
|
||||
if (!open) {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -51,6 +51,6 @@ function fill(el, model) {
|
||||
startButton.onclick = () => void start(false);
|
||||
const discussButton = h("button", { disabled: busy, title: "Start a task that discusses it with you in chat before building anything" }, "discuss");
|
||||
discussButton.onclick = () => void start(true);
|
||||
replace(action, startButton, h("span", { class: "todo-sep" }, " · "), discussButton);
|
||||
replace(action, startButton, discussButton);
|
||||
}
|
||||
//# sourceMappingURL=todolink.js.map
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"todolink.js","sourceRoot":"","sources":["../src/todolink.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"todolink.js","sourceRoot":"","sources":["../src/todolink.ts"],"names":[],"mappings":"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"}
|
||||
Reference in New Issue
Block a user