Add a Discuss button beside Start on TODO items

This commit is contained in:
Ian Gulliver
2026-10-16 08:53:02 -07:00
parent cac24e534f
commit 2bb7833de3
14 changed files with 227 additions and 205 deletions
+2
View File
@@ -892,6 +892,8 @@ export interface components {
/** @description The title of the item to start. */
title: string;
model?: string;
/** @description Tell the agent the human wants to talk the item through, so it asks before changing anything. */
discuss?: boolean;
};
Unmerged: {
/** @description Commits on the task branch that aren't on the default branch. */
+9 -7
View File
@@ -41,12 +41,12 @@ export function mountProject(root: HTMLElement): () => void {
}
};
const start = async (project: Project, item: TodoItem) => {
const start = async (project: Project, item: TodoItem, discuss: boolean) => {
const key = `${project.id}\n${item.title}`;
starting.add(key);
render();
try {
await post("/api/projects/{projectId}/todo/tasks", { path: { projectId: project.id }, body: { title: item.title, model: models[0] } });
await post("/api/projects/{projectId}/todo/tasks", { path: { projectId: project.id }, body: { title: item.title, model: models[0], discuss } });
} catch (err) {
void showAlert(errorText(err));
}
@@ -93,7 +93,7 @@ export function mountProject(root: HTMLElement): () => void {
};
}
function projectBlock(project: Project, todo: Todo | string | undefined, starting: Set<string>, start: (p: Project, item: TodoItem) => Promise<void>): HTMLElement {
function projectBlock(project: Project, todo: Todo | string | undefined, starting: Set<string>, start: (p: Project, item: TodoItem, discuss: boolean) => Promise<void>): HTMLElement {
const active = (state.tasks.get(project.id) ?? []).filter((t) => t.status === "active");
return h(
"section",
@@ -139,7 +139,7 @@ function tasksBlock(active: Task[]): HTMLElement {
);
}
function todoBlock(project: Project, todo: Todo | string | undefined, active: Task[], starting: Set<string>, start: (p: Project, item: TodoItem) => Promise<void>): HTMLElement[] {
function todoBlock(project: Project, todo: Todo | string | undefined, active: Task[], starting: Set<string>, start: (p: Project, item: TodoItem, discuss: boolean) => Promise<void>): HTMLElement[] {
if (todo === undefined) {
return [h("p", { class: "empty-row" }, "Loading…")];
}
@@ -185,9 +185,11 @@ function todoBlock(project: Project, todo: Todo | string | undefined, active: Ta
);
} else {
const busy = starting.has(`${project.id}\n${item.title}`);
const button = h("button", { disabled: busy }, busy ? "Starting…" : "Start");
button.onclick = () => void start(project, item);
action = button;
const startButton = h("button", { disabled: busy, title: "Start a task that gets straight to work" }, busy ? "Starting…" : "Start");
startButton.onclick = () => void start(project, item, false);
const discussButton = h("button", { disabled: busy, title: "Start a task that talks it through with you before changing anything" }, "Discuss");
discussButton.onclick = () => void start(project, item, true);
action = h("span", { class: "todo-buttons" }, startButton, discussButton);
}
list.append(
+7 -4
View File
@@ -49,17 +49,20 @@ function fill(el: HTMLElement, model: string): void {
titleEl.classList.remove("task-name");
const key = `${projectId}\n${title}`;
const busy = starting.has(key);
const button = h("button", { disabled: busy }, busy ? "Starting…" : "Start");
button.onclick = async () => {
const start = async (discuss: boolean) => {
starting.add(key);
fill(el, model);
try {
await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model } });
await post("/api/projects/{projectId}/todo/tasks", { path: { projectId }, body: { title, model, discuss } });
} catch (err) {
void showAlert(errorText(err));
}
starting.delete(key);
fill(el, model);
};
replace(action, button);
const startButton = h("button", { disabled: busy, title: "Start a task that gets straight to work" }, busy ? "Starting…" : "Start");
startButton.onclick = () => void start(false);
const discussButton = h("button", { disabled: busy, title: "Start a task that talks it through with you before changing anything" }, "Discuss");
discussButton.onclick = () => void start(true);
replace(action, startButton, " ", discussButton);
}