feat: session source in session_meta and an Automated sidebar folder (#40)

Co-authored-by: Alice <alice@prismshadow.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-07-23 00:58:43 +08:00
1 parent e0bf1706b9
commit c380113e26
30 files changed
+1023 -74

No files matched your search

+31 -3
View File
@@ -105,11 +105,39 @@ test("subagent card survives a reload; child session title is generated from its
await openSubagent();
// --- Child session title: generated by the model from the child session's own conversation (async, poll until persisted) ---
const childTitle = async () => {
const childOf = async () => {
const list = await (
await page.request.get(`${BASE}/api/projects/${projectId}/agents/${agentId}/sessions`)
).json();
return list.sessions.find((s) => s.sessionId !== sessionId)?.title ?? null;
return list.sessions.find((s) => s.sessionId !== sessionId) ?? null;
};
await expect.poll(childTitle, { timeout: 10000 }).toBe("Subagent TODO summary");
await expect
.poll(async () => (await childOf())?.title ?? null, { timeout: 10000 })
.toBe("Subagent TODO summary");
const child = await childOf();
// --- The child's OWN Trace session_meta records source=subagent: written by core's spawn
// site, the single source of truth (the server's registration fallback cannot mask this —
// it never writes the child Trace), and what the derived list source ultimately rests on. ---
const childMessages = await (
await page.request.get(`${BASE}/api/sessions/${child.sessionId}/messages`)
).json();
const childMeta = childMessages.messages.find(
(m) => m.type === "session_meta" && !m.origin?.length,
);
expect(childMeta, "child trace session_meta").toBeTruthy();
expect(childMeta.payload.source).toBe("subagent");
// --- Sidebar: the child session (source=subagent) nests inside the collapsed "Subagents"
// folder (per-origin folders sit parallel to "Archived" within the same temp-workspace
// group). Reload first so the sidebar list carries the persisted title/source, and the
// folder is back to its default collapsed state. ---
await page.reload();
const sidebar = page.getByRole("complementary");
const subagentFolder = sidebar.getByRole("button", { name: "子智能体(1)" });
await expect(subagentFolder, "collapsed Subagents folder").toBeVisible();
// Collapsed by default: the child row is not rendered until the folder is expanded.
await expect(sidebar.getByText("Subagent TODO summary")).toHaveCount(0);
await subagentFolder.click();
await expect(sidebar.getByText("Subagent TODO summary")).toBeVisible();
});