fix: derive Workbench rail titles from Kafka index
Pipelines as Code CI / hwlab-nc01-v03-ci-poll- Success

This commit is contained in:
root
2026-07-20 11:10:13 +02:00
parent 54e823e140
commit f07669fe40
7 changed files with 98 additions and 3 deletions
+15 -3
View File
@@ -73,14 +73,26 @@ function requireAuthorization(request: Request, options: { snapshot?: unknown; a
if (!expected || actual !== expected) throw Object.assign(new Error("Workbench API internal authentication failed"), { code: "auth_required" });
}
async function nativeSessionList(options: { snapshot?: () => Promise<any>; mode?: WorkbenchMode }, url: URL) {
async function nativeSessionList(options: { snapshot?: () => Promise<any>; mode?: WorkbenchMode; kafkaEventBridge?: any }, url: URL) {
const state = await requiredSnapshot(options);
const owner = text(url.searchParams.get("ownerUserId"));
const kafkaSummary = options.mode === "agentrun-native" ? options.kafkaEventBridge?.workbenchSessionSummaries?.() : null;
const kafkaSummaryBySession = new Map((Array.isArray(kafkaSummary?.sessions) ? kafkaSummary.sessions : []).map((session: any) => [text(session.sessionId), session]));
const sessions = Object.values(state.sessions)
.filter((session: any) => !owner || session.ownerUserId === owner)
.map((session: any) => ({ ...session, firstUserMessagePreview: firstUserMessagePreview(session.messages) ?? (text(session.firstUserMessagePreview) || null) }))
.map((session: any) => {
const summary = kafkaSummaryBySession.get(text(session.sessionId)) as any;
const nativeTestPreview = options.mode === "agentrun-native" ? null : firstUserMessagePreview(session.messages) ?? (text(session.firstUserMessagePreview) || null);
return {
...session,
firstUserMessagePreview: text(summary?.firstUserMessagePreview) || nativeTestPreview,
lastUserMessageAt: text(summary?.lastUserMessageAt) || null,
updatedAt: text(summary?.lastUserMessageAt) || session.updatedAt
};
})
.sort((left: any, right: any) => String(right.updatedAt).localeCompare(String(left.updatedAt)));
return json(200, { ok: true, status: "ready", sessions, count: sessions.length, mode: options.mode ?? "native-test" });
const warnings = kafkaSummary?.warning ? [kafkaSummary.warning] : [];
return json(200, { ok: true, status: "ready", sessions, count: sessions.length, warnings, mode: options.mode ?? "native-test" });
}
async function nativeSessionDetail(options: { snapshot?: () => Promise<any>; mode?: WorkbenchMode }, sessionId: string, messagesOnly: boolean) {
const state = await requiredSnapshot(options);
+29
View File
@@ -103,6 +103,35 @@ describe("Workbench native HTTP adapter", () => {
});
});
test("AgentRun native session list uses Kafka index summaries instead of admission messages", async () => {
const app = createWorkbenchHttpApp({
mode: "agentrun-native",
kafkaEventBridge: {
workbenchSessionSummaries() {
return { ok: true, sessions: [{ sessionId: "ses_title", firstUserMessagePreview: "Kafka title", lastUserMessageAt: "2026-07-20T01:00:00.000Z" }] };
}
},
async dispatch() { return { ok: true }; },
async snapshot() {
return {
sessions: {
ses_title: {
sessionId: "ses_title",
updatedAt: "2026-07-20T00:00:00.000Z",
messages: [{ role: "user", content: "admission snapshot title" }]
}
},
turns: {}
};
}
});
const response = await app.fetch(new Request("http://native.test/v1/workbench/sessions"));
expect(await response.json()).toMatchObject({
sessions: [{ sessionId: "ses_title", firstUserMessagePreview: "Kafka title", lastUserMessageAt: "2026-07-20T01:00:00.000Z" }]
});
});
test("authorizes only the Workbench navigation entry", async () => {
const app = createWorkbenchHttpApp({
async dispatch() { return { ok: true }; },