Cron detail page with output history, markdown skill rendering

- /cron/[id]: job details, prompt, output history from filesystem
- Cron list items now link to detail pages
- Skills render SKILL.md as proper markdown (headings, code, tables)
- Cron output proxy reads from ~/.hermes/cron/output/
This commit is contained in:
Hermes
2026-04-09 21:26:34 -05:00
parent e24c179e89
commit 218d12b8d7
4 changed files with 236 additions and 31 deletions
+29
View File
@@ -0,0 +1,29 @@
import { NextRequest, NextResponse } from "next/server";
import { promises as fs } from "fs";
import path from "path";
const OUTPUT_DIR = process.env.HERMES_CRON_OUTPUT || "/home/hermes/.hermes/cron/output";
export async function GET(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
const jobDir = path.join(OUTPUT_DIR, id);
try {
const files = await fs.readdir(jobDir);
const outputs = await Promise.all(
files
.filter((f) => f.endsWith(".md"))
.sort()
.reverse()
.slice(0, 20)
.map(async (f) => {
const content = await fs.readFile(path.join(jobDir, f), "utf-8");
const timestamp = f.replace(".md", "").replace(/_/g, " ");
return { timestamp, content };
})
);
return NextResponse.json({ outputs });
} catch {
return NextResponse.json({ outputs: [] });
}
}
+17
View File
@@ -0,0 +1,17 @@
import { NextRequest, NextResponse } from "next/server";
const GATEWAY = process.env.HERMES_GATEWAY_URL || "http://127.0.0.1:8642";
export async function GET(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
try {
const res = await fetch(GATEWAY + "/api/jobs/" + id);
const data = await res.text();
return new NextResponse(data, {
status: res.status,
headers: { "content-type": "application/json" },
});
} catch {
return NextResponse.json({ error: "gateway unreachable" }, { status: 502 });
}
}