Switch to Transcript after answering a task's last inbox item
This commit is contained in:
+1
-1
@@ -157,7 +157,7 @@ The **Project** tab is the dashboard of the right pane's project (the focused ta
|
|||||||
|
|
||||||
Agents ask questions with the `ask_human` MCP tool. Each question carries a `context` with the background the human needs to answer without reading the transcript, and its choices are written inline in that context as Markdown list items: `- ( ) text` for pick-one choices, with exactly one `- (*) text` marking the recommendation, or `- [ ] text` for pick-any choices, with `- [x] text` marking the recommended ones. There is no separate list of options. byre parses the choices out of `context` (`internal/agents/choices.go`; list items inside code fences and blockquotes don't count) and stores their text in the payload as `options`, with `multiple` (pick-any) and `recommended`. The UI renders the context as Markdown with a radio button or checkbox in place of each choice's marker. A malformed call (no `context` or `why_blocked`, fewer than two choices, pick-one and pick-any choices mixed, a pick-one question without exactly one recommendation, two choices with the same text, an unknown attachment kind, a foreign `thread_id`) is rejected with a message saying what to fix, and nothing is filed. The call returns the item's id as `question_id`. An agent withdraws a question it no longer needs answered (the human answered it in a chat message, say) with the `cancel_question` MCP tool and that id: an `open` question of its own session becomes `dismissed` with no `resolved_by` (its `inbox.updated` event has actor `agent`), which also stops a blocking one from holding back delivery; anything else is rejected with a message saying why. Each turn's final message (as a `report`) and each agent error (a turn that ends in error without a human interrupt, a process that dies mid-turn) also files an item.
|
Agents ask questions with the `ask_human` MCP tool. Each question carries a `context` with the background the human needs to answer without reading the transcript, and its choices are written inline in that context as Markdown list items: `- ( ) text` for pick-one choices, with exactly one `- (*) text` marking the recommendation, or `- [ ] text` for pick-any choices, with `- [x] text` marking the recommended ones. There is no separate list of options. byre parses the choices out of `context` (`internal/agents/choices.go`; list items inside code fences and blockquotes don't count) and stores their text in the payload as `options`, with `multiple` (pick-any) and `recommended`. The UI renders the context as Markdown with a radio button or checkbox in place of each choice's marker. A malformed call (no `context` or `why_blocked`, fewer than two choices, pick-one and pick-any choices mixed, a pick-one question without exactly one recommendation, two choices with the same text, an unknown attachment kind, a foreign `thread_id`) is rejected with a message saying what to fix, and nothing is filed. The call returns the item's id as `question_id`. An agent withdraws a question it no longer needs answered (the human answered it in a chat message, say) with the `cancel_question` MCP tool and that id: an `open` question of its own session becomes `dismissed` with no `resolved_by` (its `inbox.updated` event has actor `agent`), which also stops a blocking one from holding back delivery; anything else is rejected with a message saying why. Each turn's final message (as a `report`) and each agent error (a turn that ends in error without a human interrupt, a process that dies mid-turn) also files an item.
|
||||||
|
|
||||||
`GET /api/inbox` is one query over open items, oldest first; `project_id` and `task_id` narrow it to a project or task view, and `state` picks another state. Blocking questions and errors are `blocked`; reports and non-blocking questions are `fyi`. The Inbox tab is task-specific: it shows the selected task's open items in time order, and nothing when no task is selected. While the selected task has open items, the Inbox tab's button is highlighted in the warn colours (`.attention` in `web/style.css`) and carries their count.
|
`GET /api/inbox` is one query over open items, oldest first; `project_id` and `task_id` narrow it to a project or task view, and `state` picks another state. Blocking questions and errors are `blocked`; reports and non-blocking questions are `fyi`. The Inbox tab is task-specific: it shows the selected task's open items in time order, and nothing when no task is selected. While the selected task has open items, the Inbox tab's button is highlighted in the warn colours (`.attention` in `web/style.css`) and carries their count. Answering or dismissing the task's last open item from the Inbox tab switches the pane to the Transcript tab.
|
||||||
|
|
||||||
`POST /api/inbox/responses` answers any number of items in one submission. Response types and what they do to the item:
|
`POST /api/inbox/responses` answers any number of items in one submission. Response types and what they do to the item:
|
||||||
|
|
||||||
|
|||||||
Vendored
+5
-1
@@ -3,7 +3,7 @@ import { mountChanges } from "./changes.js";
|
|||||||
import { ago, errorText, h, replace, showAlert } from "./dom.js";
|
import { ago, errorText, h, replace, showAlert } from "./dom.js";
|
||||||
import { image, inlineMarkdown, markdown } from "./markdown.js";
|
import { image, inlineMarkdown, markdown } from "./markdown.js";
|
||||||
import { diagram } from "./mermaid.js";
|
import { diagram } from "./mermaid.js";
|
||||||
import { onEach, state } from "./state.js";
|
import { focusTab, onEach, state } from "./state.js";
|
||||||
import { taskStyle } from "./taskcolor.js";
|
import { taskStyle } from "./taskcolor.js";
|
||||||
const checked = new Map();
|
const checked = new Map();
|
||||||
const texts = new Map();
|
const texts = new Map();
|
||||||
@@ -100,6 +100,10 @@ function card(item) {
|
|||||||
await post("/api/inbox/responses", { body: { responses: [response] } });
|
await post("/api/inbox/responses", { body: { responses: [response] } });
|
||||||
checked.delete(item.id);
|
checked.delete(item.id);
|
||||||
texts.delete(item.id);
|
texts.delete(item.id);
|
||||||
|
const others = state.inbox.some((i) => i.task_id === item.task_id && i.id !== item.id);
|
||||||
|
if (!others && state.focus.tab === "inbox" && state.selectedTaskId === item.task_id) {
|
||||||
|
focusTab("transcript");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
void showAlert(errorText(err));
|
void showAlert(errorText(err));
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+5
-1
@@ -3,7 +3,7 @@ import { mountChanges } from "./changes.js";
|
|||||||
import { ago, errorText, h, replace, showAlert } from "./dom.js";
|
import { ago, errorText, h, replace, showAlert } from "./dom.js";
|
||||||
import { image, inlineMarkdown, markdown } from "./markdown.js";
|
import { image, inlineMarkdown, markdown } from "./markdown.js";
|
||||||
import { diagram } from "./mermaid.js";
|
import { diagram } from "./mermaid.js";
|
||||||
import { onEach, state } from "./state.js";
|
import { focusTab, onEach, state } from "./state.js";
|
||||||
import { taskStyle } from "./taskcolor.js";
|
import { taskStyle } from "./taskcolor.js";
|
||||||
|
|
||||||
const checked = new Map<string, string[]>();
|
const checked = new Map<string, string[]>();
|
||||||
@@ -123,6 +123,10 @@ function card(item: InboxItem): HTMLElement {
|
|||||||
await post("/api/inbox/responses", { body: { responses: [response] } });
|
await post("/api/inbox/responses", { body: { responses: [response] } });
|
||||||
checked.delete(item.id);
|
checked.delete(item.id);
|
||||||
texts.delete(item.id);
|
texts.delete(item.id);
|
||||||
|
const others = state.inbox.some((i) => i.task_id === item.task_id && i.id !== item.id);
|
||||||
|
if (!others && state.focus.tab === "inbox" && state.selectedTaskId === item.task_id) {
|
||||||
|
focusTab("transcript");
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
void showAlert(errorText(err));
|
void showAlert(errorText(err));
|
||||||
lock(false);
|
lock(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user