Add concurrency caps, the two-pane web UI, AGENTS.md, and plan status
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import { get, put, subscribe } from "./api.js";
|
||||
import { errorText, h, replace } 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";
|
||||
|
||||
function identityBanner(root: HTMLElement): void {
|
||||
const render = () => {
|
||||
const me = state.me;
|
||||
if (!me || (me.git_name && me.git_email)) {
|
||||
replace(root);
|
||||
root.hidden = true;
|
||||
return;
|
||||
}
|
||||
const name = h("input", { placeholder: "Git name", value: me.display_name, required: true });
|
||||
const email = h("input", { type: "email", placeholder: "Git email", required: true });
|
||||
const form = h("form", { class: "inline-form" }, "Set the identity agents commit as: ", name, email, h("button", { type: "submit" }, "Save"));
|
||||
form.onsubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
state.me = await put("/api/me", { body: { git_name: name.value, git_email: email.value } });
|
||||
render();
|
||||
} catch (err) {
|
||||
alert(errorText(err));
|
||||
}
|
||||
};
|
||||
root.hidden = false;
|
||||
replace(root, form);
|
||||
};
|
||||
on("me", render);
|
||||
render();
|
||||
}
|
||||
|
||||
function route(): void {
|
||||
const match = /^#\/task\/(\w+)$/.exec(location.hash);
|
||||
const taskId = match?.[1];
|
||||
if (taskId !== state.selectedTaskId) {
|
||||
void selectTask(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const navbar = h("header", { class: "navbar" });
|
||||
const banner = h("div", { class: "banner", hidden: true });
|
||||
const left = new Pane("left", "transcript");
|
||||
const right = new Pane("right", "inbox");
|
||||
replace(document.body, navbar, banner, h("div", { class: "panes" }, left.el, right.el));
|
||||
|
||||
mountNavbar(navbar, () => right.show("inbox"));
|
||||
identityBanner(banner);
|
||||
|
||||
const status = await get("/api/admin/status");
|
||||
await Promise.all([loadMe(), loadProjects(), loadInbox()]);
|
||||
|
||||
subscribe(status.last_event_seq, handleEvent, (connected) => {
|
||||
state.connected = connected;
|
||||
notify("connection");
|
||||
});
|
||||
|
||||
addEventListener("hashchange", route);
|
||||
route();
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
replace(document.body, h("pre", { class: "fatal" }, `byre failed to start: ${errorText(err)}`));
|
||||
});
|
||||
Reference in New Issue
Block a user