review status
This commit is contained in:
+2
-1
@@ -908,7 +908,7 @@ components:
|
||||
|
||||
Task:
|
||||
type: object
|
||||
required: [id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at]
|
||||
required: [id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, reviewing]
|
||||
properties:
|
||||
id: { type: string }
|
||||
project_id: { type: string }
|
||||
@@ -934,6 +934,7 @@ components:
|
||||
workflow: { type: string, description: "The name of the workflow the task froze at creation (getTaskWorkflow has its copy); absent for a task without one." }
|
||||
workflow_run: { type: string, description: "With workflow: the id every task of one run of the workflow shares." }
|
||||
workflow_stage: { type: string, description: "With workflow: the name of the stage this task runs." }
|
||||
reviewing: { type: boolean, description: "Whether a review of one of the task's snapshots is running." }
|
||||
|
||||
Todo:
|
||||
type: object
|
||||
|
||||
+2
-2
@@ -135,7 +135,7 @@ Event payloads are stored whole in `events.payload`, and `agent.tool_result` con
|
||||
|
||||
Messages byre itself sends an agent (actor `byre`: the restart notice, Sync and Merge prompts, Compact's handoff request) show collapsed like a tool call, labelled `byre` with the first line as the brief; expanding it shows the full text. The transcript view has a border in the task's colour (see "Task colours"; the accent in the lead pane) while the session is `running` and its transcript has an open turn (`ctx.open`: a drawn turn-starting `user.message`, not mid-turn, with no `turn.ended` after it), and a Cylon-style scanner in the same colour: a row of 2px dots, 5px apart along an 84px track, where a glow sweeping back and forth every 1.2s lights up the dots under it, drawn below the last message, in the transcript's bottom padding, so it scrolls with the transcript and sits just above the composer's top border when scrolled to the bottom. It takes no height (`.scanner` is a zero-height element kept as the transcript's last child, with a negative top margin that cancels the flex gap before it, and its `::before` draws the bar inside the bottom padding), so showing or hiding it never changes the transcript's scroll height or position. It is one element with one CSS animation: the `cylon` keyframes in `web/style.css` slide a gradient's `background-position` along the track, under a static repeating mask that cuts it into dots. Orion freezes animated GIFs and per-dot `step-end` opacity animations partway through a turn, so it stays a single element with a single animation. The session list (`GET /api/me/lead/sessions` or the task's sessions) is fetched separately from the event stream, so it says `running` a little before the turn's `user.message` arrives and a little after its `turn.ended`; requiring the open turn as well keeps the scanner and border from flashing on in those gaps. Consecutive tool calls (with any thinking between them) collapse into one group whose summary counts calls per tool and file, and file paths show relative to the worktree. byre's own tools show without their `mcp__byre__` prefix, in title case (`mcp__byre__create_task` shows as Create Task; `toolLabel` in `web/src/task.ts`); other tools show under the name the agent used. A Claude Code subagent call (the `Agent` or `Task` tool) stands on its own, collapsed, labelled with its `subagent_type` and `description`; expanding it shows the prompt and the call's result. Its summary carries a status from the `agent.vendor` `system` events whose `tool_use_id` names it (`task_started`: running, or running in the background; `task_progress`: its `description`; `task_notification`: its `status`, red unless `completed`). The subagent's own messages, thinking and tool calls (events whose `parent_tool_use_id` names the call) stream inline with the main agent's, in arrival order, each marked `↳ <subagent_type>` with the description as its tooltip; its messages also get an accent rule down their left edge. A run of tool calls groups only calls from the same agent, so a call from another agent starts a new group. A subagent's messages never end the main agent's live message, count as a turn's final message or hide a quiet turn. Claude Code streams a background subagent's activity, but for a foreground one only its prompt, so a foreground subagent shows only as its call, its status and its result. Selecting a task that has never had a session focuses the composer. In the composer, Enter sends and Shift-Enter adds a newline; unsent text is kept per task in memory, so it survives switching tabs or tasks but not a page reload. The composer has no `@`-file mentions or path picker: text reaches the agent exactly as typed (stream-json doesn't expand `@path` the way the interactive CLI does), and the agent reads any file the message names with its own tools. The composer is the same whether or not the task has a live session, and stays enabled while a turn runs: Send posts to the session's messages, or starts a session with the text when there is none or the last one completed. A sent message shows at once as a bubble reading "queued…" while the session is running and "sending…" otherwise, replaced by the server's `user.message` event with the same text when it arrives, and removed (text and images back in the composer) if the request fails.
|
||||
|
||||
The task switcher (⌘K, or the project ▸ task picker centred in the right pane's top row) lists active tasks with their session state and open inbox item count, and **merge held** on a task with `merge_queued_at`, live while it is open. Tasks with inbox items come first; within each group, the task least recently visited in this browser comes first (never-visited tasks before all others, ties in the server's order: projects by name, tasks newest first). Visit times are kept in the browser's localStorage under `byre.visits`, stamped when a task is selected and again when it is left. After the tasks come the projects, one row each; picking one points the right pane at the project with no task, on the Project tab. Typing filters both and adds a last row that creates a task with the typed text as its title, in the right pane's project (the first project when there is none); Enter picks the highlighted row. Picking a task points the right pane at it on the Inbox tab when it has open inbox items, otherwise on the Transcript tab (see "Lead agent").
|
||||
The task switcher (⌘K, or the project ▸ task picker centred in the right pane's top row) lists active tasks with their session state and open inbox item count (the Project tab's task list shows the same state), and **merge held** on a task with `merge_queued_at`, live while it is open. Tasks with inbox items come first; within each group, the task least recently visited in this browser comes first (never-visited tasks before all others, ties in the server's order: projects by name, tasks newest first). Visit times are kept in the browser's localStorage under `byre.visits`, stamped when a task is selected and again when it is left. After the tasks come the projects, one row each; picking one points the right pane at the project with no task, on the Project tab. Typing filters both and adds a last row that creates a task with the typed text as its title, in the right pane's project (the first project when there is none); Enter picks the highlighted row. Picking a task points the right pane at it on the Inbox tab when it has open inbox items, otherwise on the Transcript tab (see "Lead agent").
|
||||
|
||||
**Task colours.** Each task has a colour, `tasks.color` (`color` in the API), an index into the palette of `--task-0` … `--task-N` custom properties at the top of `web/style.css`, one set for light and one for dark, all at least 4.5:1 against the backgrounds so they work as text. `CreateTask` assigns it in the same transaction as the task's row: of the `store.TaskColors` colours, one no active task holds, and among those the one given out longest ago (the lowest `max(rowid)` of tasks with that colour, never-used first), so a new task doesn't take the colour of one just closed. Active tasks have distinct colours until more than `TaskColors` are active at once. `TaskColors` must match the number of palette entries. An element styled with `taskStyle(id)` (`web/src/taskcolor.ts`) sets `--task` for itself and its children from the task's `color`; `--task` defaults to the accent, which is also what a task the page doesn't know gets. The right pane sets it for the selected task, which tints the picker's row, colours the task picker's text, the selected tab's underline, the composer's border and the running border and scanner. Everywhere a task is named it shows in its colour: task titles in the switcher, the Project tab and the Status tab (`.task-name`), and task links (`a.task-link`), including any Markdown link to `#/task/<id>` or `#/task/<id>/<tab>`. The lead's guidance tells it to link every task it names that way, using `#/task/<id>/inbox` when it points the human at the task's inbox, and clicking one points the right pane at the task, selecting the named tab if there is one.
|
||||
|
||||
@@ -250,7 +250,7 @@ Every new snapshot of a task gets a review: a separate agent session on the vend
|
||||
- **Screenshots.** Reviewer sessions also get the Playwright MCP server (`playwrightMCP` in `internal/agents/review.go`: `npx @playwright/mcp` at a pinned version, headless Chrome, isolated profile, absolute file paths), passed to Claude as a `stdio` entry in `--mcp-config` and to Codex as `mcp_servers` in the thread's `config`. Its automatically named files go to `worktrees/<project-id>/review-<review-id>-media`, removed with the checkout. Each `images` entry is `{path, caption}`, the path absolute or relative to the checkout; at `submit_review` byre reads every one, refuses the whole submission (nothing recorded) for a missing file or one that isn't one of `store.ImageTypes` within `store.MaxBlobBytes`, then stores each as a blob and replaces its `path` with `blob`, since the files are deleted with the checkout. They run without the Stop-hook bounce, mid-turn delivery, end-of-turn commit, snapshots or turn summaries, and their `user.message` events carry no `head`. When the reviewer's turn ends byre completes its session, kills its process and removes the worktree; a review still `running` then fails with why (no submission, with the final message; an error; an interrupt). A process that exits mid-turn fails the review the same way. Merging or discarding the task fails its running reviews ("the task was closed") and ends their reviewers. On startup, a running reviewer resumes like any session, and a running review whose reviewer isn't `running` fails.
|
||||
- **Questions.** A question's `reviews` is the review of the first snapshot the task took after the question was filed, the one at the end of the turn that asked it, computed when the item is read; the Inbox tab shows it under the question once it starts.
|
||||
- **Events.** `review.started` and `review.finished` (state `done`, `failed` or `skipped`; a skipped review emits only `review.finished`) carry the whole review, with the task's ids and no `agent_session_id`. A reviewer's own events carry its session id and the task's ids: the transcript skips every event of a session whose `session.created` has `role` `reviewer`, and draws each `review.finished` as a note with its outcome; the lead's `read_transcript` leaves the reviewer's events out and shows each `review.finished` with its summary and findings (`reviewLine`). `GET /api/tasks/{taskId}/sessions` and everything that looks for the task's agent (`ListSessions`) see only implementer sessions.
|
||||
- **UI.** The **Reviews** tab (`web/src/reviews.ts`) shows one review at a time, picked by snapshot (see "Snapshots" for the picker): its snapshot, state or severity counts, error, `change`, summary, screenshots and findings. A finding with `path` and `line` shows, under its title, the lines `line` to `end_line` plus 3 either side from that file's diff for the snapshot's step (`changes?snapshot=<n>&step=true`, the diff the reviewer was given), with new-file line numbers and the finding's own lines marked; it shows nothing when those lines aren't in the diff, and "diff not available" with the error once the task is closed. Screenshots link to the full image. Each finding has a **fix** button (also on review cards in the inbox) that sends the finding's severity, title, location and detail to the task's agent as a message from the user: through `POST /api/sessions/{id}/messages` to its latest live session (queued like any message while the agent is mid-turn, see "Agent sessions"), or starting a session when it has none. Once sent, the right pane switches to that task's Transcript tab. It loads when it opens, when the task changes, and on each `review.*` event in the task's stream. When the finished review of the highest-numbered snapshot has findings, the tab (or the More menu holding it) is highlighted with a badge of the finding count. Each snapshot row's **review** button carries a mark over its top-right corner from that snapshot's latest `review.*` event: a spinner while the review runs, a grey ● when it was skipped, a green ✓ when it finished with no findings, and, when it has findings, the button highlighted with the count in a badge. A failed review leaves the button unmarked. `GET /api/tasks/{taskId}/reviews` lists a task's reviews oldest first. `sqlite3 byre.db "SELECT id, task_id, snapshot_n, vendor, state, error FROM reviews ORDER BY created_at DESC LIMIT 20"` shows recent ones.
|
||||
- **UI.** The **Reviews** tab (`web/src/reviews.ts`) shows one review at a time, picked by snapshot (see "Snapshots" for the picker): its snapshot, state or severity counts, error, `change`, summary, screenshots and findings. A finding with `path` and `line` shows, under its title, the lines `line` to `end_line` plus 3 either side from that file's diff for the snapshot's step (`changes?snapshot=<n>&step=true`, the diff the reviewer was given), with new-file line numbers and the finding's own lines marked; it shows nothing when those lines aren't in the diff, and "diff not available" with the error once the task is closed. Screenshots link to the full image. Each finding has a **fix** button (also on review cards in the inbox) that sends the finding's severity, title, location and detail to the task's agent as a message from the user: through `POST /api/sessions/{id}/messages` to its latest live session (queued like any message while the agent is mid-turn, see "Agent sessions"), or starting a session when it has none. Once sent, the right pane switches to that task's Transcript tab. It loads when it opens, when the task changes, and on each `review.*` event in the task's stream. When the finished review of the highest-numbered snapshot has findings, the tab (or the More menu holding it) is highlighted with a badge of the finding count. Each snapshot row's **review** button carries a mark over its top-right corner from that snapshot's latest `review.*` event: a spinner while the review runs, a grey ● when it was skipped, a green ✓ when it finished with no findings, and, when it has findings, the button highlighted with the count in a badge. A failed review leaves the button unmarked. A Task's `reviewing` is true while any of its reviews is `running`, and the global stream's `review.*` events reload that project's tasks; the task switcher and the Project tab's task list show **reviewing**, with the running dot, in place of an `idle` session state (`taskState` in `web/src/state.ts`). `GET /api/tasks/{taskId}/reviews` lists a task's reviews oldest first. `sqlite3 byre.db "SELECT id, task_id, snapshot_n, vendor, state, error FROM reviews ORDER BY created_at DESC LIMIT 20"` shows recent ones.
|
||||
|
||||
## Workflows
|
||||
|
||||
|
||||
+176
-173
@@ -873,8 +873,11 @@ type Task struct {
|
||||
MergeTitle string `json:"merge_title"`
|
||||
|
||||
// PortBase The first of the task's block of ports (port_base to port_base+9), passed to its agent and terminal as PORT.
|
||||
PortBase int `json:"port_base"`
|
||||
ProjectId string `json:"project_id"`
|
||||
PortBase int `json:"port_base"`
|
||||
ProjectId string `json:"project_id"`
|
||||
|
||||
// Reviewing Whether a review of one of the task's snapshots is running.
|
||||
Reviewing bool `json:"reviewing"`
|
||||
Status TaskStatus `json:"status"`
|
||||
Title string `json:"title"`
|
||||
|
||||
@@ -2894,177 +2897,177 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
|
||||
// const string: with thousands of chunks the chained `+` fold is several
|
||||
// times slower for the Go compiler than parsing a slice literal.
|
||||
var swaggerSpec = []string{
|
||||
"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",
|
||||
}
|
||||
|
||||
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
|
||||
|
||||
@@ -1322,7 +1322,7 @@ func (s *Store) write(ctx context.Context, fn func(tx *sql.Tx, emit emitFunc) er
|
||||
|
||||
const projectColumns = `id, name, repo_path, default_branch, remote, created_by, created_at`
|
||||
|
||||
const taskColumns = `id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, closed_at, merge_commit, todo_item, forked_from, forked_at, merge_queued_at, workflow_name, workflow_run, workflow_stage`
|
||||
const taskColumns = `id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, closed_at, merge_commit, todo_item, forked_from, forked_at, merge_queued_at, workflow_name, workflow_run, workflow_stage, EXISTS (SELECT 1 FROM reviews WHERE reviews.task_id = tasks.id AND reviews.state = 'running')`
|
||||
|
||||
const sessionColumns = `id, coalesce(task_id, ''), owner, vendor, model, vendor_session_id, state, role, created_by, created_at, forked_from, forked_at`
|
||||
|
||||
@@ -1354,7 +1354,7 @@ func scanTask(row scanner) (api.Task, error) {
|
||||
workflowName := ""
|
||||
workflowRun := ""
|
||||
workflowStage := ""
|
||||
err := row.Scan(&t.Id, &t.ProjectId, &t.Title, &t.MergeTitle, &t.Branch, &t.WorktreePath, &t.BaseRef, &t.PortBase, &t.Color, &status, &t.CreatedBy, &createdAt, &closedAt, &mergeCommit, &todoItem, &forkedFrom, &forkedAt, &mergeQueuedAt, &workflowName, &workflowRun, &workflowStage)
|
||||
err := row.Scan(&t.Id, &t.ProjectId, &t.Title, &t.MergeTitle, &t.Branch, &t.WorktreePath, &t.BaseRef, &t.PortBase, &t.Color, &status, &t.CreatedBy, &createdAt, &closedAt, &mergeCommit, &todoItem, &forkedFrom, &forkedAt, &mergeQueuedAt, &workflowName, &workflowRun, &workflowStage, &t.Reviewing)
|
||||
if err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
||||
Vendored
+3
-3
@@ -2,7 +2,7 @@ import { get, post } from "./api.js";
|
||||
import { errorText, h, replace, showAlert } from "./dom.js";
|
||||
import { markdown } from "./markdown.js";
|
||||
import { models } from "./task.js";
|
||||
import { currentSession, focusedProject, focusTask, on, onEach, state } from "./state.js";
|
||||
import { currentSession, focusedProject, focusTask, on, onEach, state, taskState } from "./state.js";
|
||||
import { taskStyle } from "./taskcolor.js";
|
||||
const refreshKinds = new Set(["task.merged", "project.created"]);
|
||||
export function mountProject(root) {
|
||||
@@ -91,7 +91,7 @@ function tasksBlock(active) {
|
||||
return h("p", { class: "empty-row" }, "No active tasks.");
|
||||
}
|
||||
return h("ul", { class: "task-list" }, ...active.map((task) => {
|
||||
const sess = currentSession(task.id);
|
||||
const ts = taskState(task);
|
||||
const count = state.inbox.filter((item) => item.task_id === task.id).length;
|
||||
return h("li", { class: task.id === state.selectedTaskId ? "selected" : "", style: taskStyle(task.id) }, h("a", {
|
||||
href: `#/task/${task.id}`,
|
||||
@@ -99,7 +99,7 @@ function tasksBlock(active) {
|
||||
e.preventDefault();
|
||||
focusTask(task.id);
|
||||
},
|
||||
}, h("span", { class: `dot ${sess?.state ?? "none"}`, title: sess?.state ?? "no session" }), h("span", { class: "task-title task-name" }, task.title), count > 0 && h("span", { class: "badge", title: "inbox items" }, count), task.merge_queued_at !== undefined && h("span", { class: "task-state warn", title: "Waiting for the merge in progress in this project to finish" }, "merge held"), h("span", { class: "task-state" }, sess?.state ?? "no agent")));
|
||||
}, h("span", { class: `dot ${ts ?? "none"}`, title: ts ?? "no session" }), h("span", { class: "task-title task-name" }, task.title), count > 0 && h("span", { class: "badge", title: "inbox items" }, count), task.merge_queued_at !== undefined && h("span", { class: "task-state warn", title: "Waiting for the merge in progress in this project to finish" }, "merge held"), h("span", { class: "task-state" }, ts ?? "no agent")));
|
||||
}));
|
||||
}
|
||||
function todoBlock(project, todo, active, starting, start) {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+7
@@ -54,6 +54,10 @@ export function findTask(id) {
|
||||
export function currentSession(taskId) {
|
||||
return state.sessions.get(taskId)?.findLast((s) => s.state !== "completed") ?? state.sessions.get(taskId)?.at(-1);
|
||||
}
|
||||
export function taskState(task) {
|
||||
const s = currentSession(task.id)?.state;
|
||||
return s === "idle" && task.reviewing ? "reviewing" : s;
|
||||
}
|
||||
export function currentLead() {
|
||||
return state.leadSessions.findLast((s) => s.state !== "completed") ?? state.leadSessions.at(-1);
|
||||
}
|
||||
@@ -270,6 +274,9 @@ export function handleEvent(ev) {
|
||||
break;
|
||||
case "review.started":
|
||||
case "review.finished":
|
||||
if (ev.project_id) {
|
||||
void loadTasks(ev.project_id);
|
||||
}
|
||||
if (state.inbox.some((i) => i.task_id === ev.task_id && i.kind === "question")) {
|
||||
void loadInbox();
|
||||
}
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { post } from "./api.js";
|
||||
import { errorText, h, replace, showAlert } from "./dom.js";
|
||||
import { focusLead } from "./panes.js";
|
||||
import { activeTasks, currentSession, focusedProject, focusProject, focusTab, focusTask, lastVisits, onEach, state } from "./state.js";
|
||||
import { activeTasks, focusedProject, focusProject, focusTab, focusTask, lastVisits, onEach, state, taskState } from "./state.js";
|
||||
import { confirmMerge } from "./task.js";
|
||||
import { taskStyle } from "./taskcolor.js";
|
||||
export function bindShortcuts() {
|
||||
@@ -79,8 +79,8 @@ export function openSwitcher() {
|
||||
.map((m) => ({ ...m, count: inbox(m.task.id), visited: visits[m.task.id] ?? 0 }))
|
||||
.sort((a, b) => Number(b.count > 0) - Number(a.count > 0) || a.visited - b.visited);
|
||||
rows = matches.map(({ project, task, count }) => {
|
||||
const sess = currentSession(task.id);
|
||||
const el = h("li", { style: taskStyle(task.id) }, h("span", { class: `dot ${sess?.state ?? "none"}`, title: sess?.state ?? "no session" }), h("span", { class: "task-title" }, h("span", { class: "project-name" }, project.name), " ", h("span", { class: "task-name" }, task.title)), count > 0 && h("span", { class: "badge", title: "inbox items" }, count), task.merge_queued_at !== undefined && h("span", { class: "task-state warn", title: "Waiting for the merge in progress in this project to finish" }, "merge held"), h("span", { class: "task-state" }, sess?.state ?? "no agent"));
|
||||
const ts = taskState(task);
|
||||
const el = h("li", { style: taskStyle(task.id) }, h("span", { class: `dot ${ts ?? "none"}`, title: ts ?? "no session" }), h("span", { class: "task-title" }, h("span", { class: "project-name" }, project.name), " ", h("span", { class: "task-name" }, task.title)), count > 0 && h("span", { class: "badge", title: "inbox items" }, count), task.merge_queued_at !== undefined && h("span", { class: "task-state warn", title: "Waiting for the merge in progress in this project to finish" }, "merge held"), h("span", { class: "task-state" }, ts ?? "no agent"));
|
||||
return { el, pick: () => go(task.id) };
|
||||
});
|
||||
for (const p of state.projects.filter((p) => `${p.name} project`.toLowerCase().includes(q))) {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -872,6 +872,8 @@ export interface components {
|
||||
workflow_run?: string;
|
||||
/** @description With workflow: the name of the stage this task runs. */
|
||||
workflow_stage?: string;
|
||||
/** @description Whether a review of one of the task's snapshots is running. */
|
||||
reviewing: boolean;
|
||||
};
|
||||
Todo: {
|
||||
/** @description Whether the default branch has a TODO.md at its root. */
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@ import { get, post, type ByreEvent, type Project, type Schemas, type Task } from
|
||||
import { errorText, h, replace, showAlert } from "./dom.js";
|
||||
import { markdown } from "./markdown.js";
|
||||
import { models } from "./task.js";
|
||||
import { currentSession, focusedProject, focusTask, on, onEach, state } from "./state.js";
|
||||
import { currentSession, focusedProject, focusTask, on, onEach, state, taskState } from "./state.js";
|
||||
import { taskStyle } from "./taskcolor.js";
|
||||
|
||||
type Todo = Schemas["Todo"];
|
||||
@@ -114,7 +114,7 @@ function tasksBlock(active: Task[]): HTMLElement {
|
||||
"ul",
|
||||
{ class: "task-list" },
|
||||
...active.map((task) => {
|
||||
const sess = currentSession(task.id);
|
||||
const ts = taskState(task);
|
||||
const count = state.inbox.filter((item) => item.task_id === task.id).length;
|
||||
return h(
|
||||
"li",
|
||||
@@ -128,11 +128,11 @@ function tasksBlock(active: Task[]): HTMLElement {
|
||||
focusTask(task.id);
|
||||
},
|
||||
},
|
||||
h("span", { class: `dot ${sess?.state ?? "none"}`, title: sess?.state ?? "no session" }),
|
||||
h("span", { class: `dot ${ts ?? "none"}`, title: ts ?? "no session" }),
|
||||
h("span", { class: "task-title task-name" }, task.title),
|
||||
count > 0 && h("span", { class: "badge", title: "inbox items" }, count),
|
||||
task.merge_queued_at !== undefined && h("span", { class: "task-state warn", title: "Waiting for the merge in progress in this project to finish" }, "merge held"),
|
||||
h("span", { class: "task-state" }, sess?.state ?? "no agent"),
|
||||
h("span", { class: "task-state" }, ts ?? "no agent"),
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
||||
+9
-1
@@ -82,7 +82,12 @@ export function currentSession(taskId: string): AgentSession | undefined {
|
||||
return state.sessions.get(taskId)?.findLast((s) => s.state !== "completed") ?? state.sessions.get(taskId)?.at(-1);
|
||||
}
|
||||
|
||||
export function currentLead(): AgentSession | undefined {
|
||||
export function taskState(task: Task): string | undefined {
|
||||
const s = currentSession(task.id)?.state;
|
||||
return s === "idle" && task.reviewing ? "reviewing" : s;
|
||||
}
|
||||
|
||||
export function currentLead():AgentSession | undefined {
|
||||
return state.leadSessions.findLast((s) => s.state !== "completed") ?? state.leadSessions.at(-1);
|
||||
}
|
||||
|
||||
@@ -328,6 +333,9 @@ export function handleEvent(ev: ByreEvent): void {
|
||||
break;
|
||||
case "review.started":
|
||||
case "review.finished":
|
||||
if (ev.project_id) {
|
||||
void loadTasks(ev.project_id);
|
||||
}
|
||||
if (state.inbox.some((i) => i.task_id === ev.task_id && i.kind === "question")) {
|
||||
void loadInbox();
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import { post } from "./api.js";
|
||||
import { errorText, h, replace, showAlert } from "./dom.js";
|
||||
import { focusLead } from "./panes.js";
|
||||
import { activeTasks, currentSession, focusedProject, focusProject, focusTab, focusTask, lastVisits, onEach, state } from "./state.js";
|
||||
import { activeTasks, focusedProject, focusProject, focusTab, focusTask, lastVisits, onEach, state, taskState } from "./state.js";
|
||||
import { confirmMerge } from "./task.js";
|
||||
import { taskStyle } from "./taskcolor.js";
|
||||
|
||||
@@ -82,15 +82,15 @@ export function openSwitcher(): void {
|
||||
.map((m) => ({ ...m, count: inbox(m.task.id), visited: visits[m.task.id] ?? 0 }))
|
||||
.sort((a, b) => Number(b.count > 0) - Number(a.count > 0) || a.visited - b.visited);
|
||||
rows = matches.map(({ project, task, count }) => {
|
||||
const sess = currentSession(task.id);
|
||||
const ts = taskState(task);
|
||||
const el = h(
|
||||
"li",
|
||||
{ style: taskStyle(task.id) },
|
||||
h("span", { class: `dot ${sess?.state ?? "none"}`, title: sess?.state ?? "no session" }),
|
||||
h("span", { class: `dot ${ts ?? "none"}`, title: ts ?? "no session" }),
|
||||
h("span", { class: "task-title" }, h("span", { class: "project-name" }, project.name), " ", h("span", { class: "task-name" }, task.title)),
|
||||
count > 0 && h("span", { class: "badge", title: "inbox items" }, count),
|
||||
task.merge_queued_at !== undefined && h("span", { class: "task-state warn", title: "Waiting for the merge in progress in this project to finish" }, "merge held"),
|
||||
h("span", { class: "task-state" }, sess?.state ?? "no agent"),
|
||||
h("span", { class: "task-state" }, ts ?? "no agent"),
|
||||
);
|
||||
return { el, pick: () => go(task.id) };
|
||||
});
|
||||
|
||||
+2
-1
@@ -540,7 +540,8 @@ a.task-link {
|
||||
box-shadow: inset 0 0 0 1.5px var(--muted);
|
||||
}
|
||||
|
||||
.dot.running {
|
||||
.dot.running,
|
||||
.dot.reviewing {
|
||||
background: var(--ok);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user