Enhance Beryl Agent detail and report views

This commit is contained in:
Beryl
2026-09-11 11:13:24 +08:00
parent 336bf88466
commit 15f067fff9
57 changed files with 1833 additions and 95 deletions
+33 -3
View File
@@ -5,11 +5,12 @@ import { randomUUID } from "node:crypto";
import { readFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { AdsMonitor } from "./monitor.js";
import {
MessageInputSchema,
ModelConnectionInputSchema,
} from "@agent-studio/shared";
import { SessionRegistry, SkillCatalog } from "@agent-studio/harness";
import { SessionRegistry, SkillCatalog, validatedPpt } from "@agent-studio/harness";
const root = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"../../../",
@@ -28,16 +29,32 @@ export async function buildApp() {
},
});
const registry = new SessionRegistry(root);
const monitor = new AdsMonitor(path.join(root,"workspace/monitoring"));
await monitor.init();
registry.monitorSnapshot = () => ({ ...monitor.state, busy: monitor.busy });
registry.monitoringBusy = () => monitor.busy;
monitor.canCheck = () => !registry.hasActiveRuns();
app.addHook("onClose",async()=>monitor.close());
app.get("/api/monitoring",async()=>({ ...monitor.state,busy:monitor.busy }));
app.post("/api/monitoring/check",async()=>monitor.check());
app.put("/api/monitoring/settings",async req=>monitor.configure(req.body));
app.post("/api/monitoring/handled",async req=>{
const key=(req.body as {key?:unknown})?.key;
if(typeof key!=="string") throw new Error("INVALID_ALERT_KEY");
return monitor.handle(key);
});
await registry.restore();
const skills = new SkillCatalog(root);
await skills.reload();
app.decorate("registry", registry);
app.get("/health", async (req) => ({ ok: true, requestId: req.id }));
app.get("/api/skills", async (req) => ({
skills: skills.items,
skills: await skills.reload(),
requestId: req.id,
}));
app.post("/api/sessions", async (req, reply) => {
const s = await registry.create();
const resumeId = (req.body as { resumeSessionId?: unknown } | undefined)?.resumeSessionId;
const s = typeof resumeId === "string" ? registry.get(resumeId) ?? await registry.create() : await registry.create();
return reply.code(201).send({ sessionId: s.sessionId, requestId: req.id });
});
app.delete("/api/sessions/:id", async (req, reply) => {
@@ -127,6 +144,12 @@ export async function buildApp() {
app.get("/api/sessions/:id/reports/:kind", async (req, reply) => {
const params = req.params as { id: string; kind: string };
const session = registry.require(params.id);
if (params.kind === "document") {
const body = await readFile(session.workspace.resolve("report.md"));
return reply.header("cache-control", "no-store")
.header("content-disposition", 'attachment; filename="report.md"')
.type("text/markdown; charset=utf-8").send(body);
}
if (params.kind !== "daily" && params.kind !== "weekly")
throw Object.assign(new Error("REPORT_KIND_NOT_FOUND"), { statusCode: 404 });
const file = session.workspace.resolve(`swads-${params.kind}-report.png`);
@@ -182,6 +205,13 @@ export async function buildApp() {
const runId = await registry.run(s, promptText, images);
return reply.code(202).send({ runId, requestId: req.id });
});
app.get("/api/sessions/:id/presentations/:artifact", async (req, reply) => {
const { id, artifact } = req.params as { id: string; artifact: string };
const bytes = await validatedPpt(registry.require(id).workspace, artifact);
return reply.header("cache-control", "no-store")
.header("content-disposition", 'attachment; filename="beryl-report.pptx"')
.type("application/vnd.openxmlformats-officedocument.presentationml.presentation").send(bytes);
});
app.post("/api/sessions/:id/cancel", async (req) => {
await registry.cancel((req.params as { id: string }).id);
return { ok: true, requestId: req.id };