mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-30 11:21:07 +00:00
fix(regression): preserve subagent session ownership metadata
This commit is contained in:
@@ -155,6 +155,11 @@ function emitSessionsChanged(
|
||||
chatType: sessionRow.chatType,
|
||||
origin: sessionRow.origin,
|
||||
spawnedBy: sessionRow.spawnedBy,
|
||||
spawnedWorkspaceDir: sessionRow.spawnedWorkspaceDir,
|
||||
forkedFromParent: sessionRow.forkedFromParent,
|
||||
spawnDepth: sessionRow.spawnDepth,
|
||||
subagentRole: sessionRow.subagentRole,
|
||||
subagentControlScope: sessionRow.subagentControlScope,
|
||||
label: sessionRow.label,
|
||||
displayName: sessionRow.displayName,
|
||||
deliveryContext: sessionRow.deliveryContext,
|
||||
|
||||
@@ -705,6 +705,64 @@ describe("gateway server sessions", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("sessions.changed mutation events include subagent ownership metadata", async () => {
|
||||
await createSessionStoreDir();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"subagent:child": {
|
||||
sessionId: "sess-child",
|
||||
updatedAt: Date.now(),
|
||||
spawnedBy: "agent:main:main",
|
||||
spawnedWorkspaceDir: "/tmp/subagent-workspace",
|
||||
forkedFromParent: true,
|
||||
spawnDepth: 2,
|
||||
subagentRole: "orchestrator",
|
||||
subagentControlScope: "children",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const broadcastToConnIds = vi.fn();
|
||||
const respond = vi.fn();
|
||||
const sessionsHandlers = await getSessionsHandlers();
|
||||
await sessionsHandlers["sessions.patch"]({
|
||||
req: {} as never,
|
||||
params: {
|
||||
key: "subagent:child",
|
||||
label: "Child",
|
||||
},
|
||||
respond,
|
||||
context: {
|
||||
broadcastToConnIds,
|
||||
getSessionEventSubscriberConnIds: () => new Set(["conn-1"]),
|
||||
loadGatewayModelCatalog: async () => ({ providers: [] }),
|
||||
} as never,
|
||||
client: null,
|
||||
isWebchatConnect: () => false,
|
||||
});
|
||||
|
||||
expect(respond).toHaveBeenCalledWith(
|
||||
true,
|
||||
expect.objectContaining({ ok: true, key: "agent:main:subagent:child" }),
|
||||
undefined,
|
||||
);
|
||||
expect(broadcastToConnIds).toHaveBeenCalledWith(
|
||||
"sessions.changed",
|
||||
expect.objectContaining({
|
||||
sessionKey: "agent:main:subagent:child",
|
||||
reason: "patch",
|
||||
spawnedBy: "agent:main:main",
|
||||
spawnedWorkspaceDir: "/tmp/subagent-workspace",
|
||||
forkedFromParent: true,
|
||||
spawnDepth: 2,
|
||||
subagentRole: "orchestrator",
|
||||
subagentControlScope: "children",
|
||||
}),
|
||||
new Set(["conn-1"]),
|
||||
{ dropIfSlow: true },
|
||||
);
|
||||
});
|
||||
|
||||
test("lists and patches session store via sessions.* RPC", async () => {
|
||||
const { dir, storePath } = await createSessionStoreDir();
|
||||
const now = Date.now();
|
||||
|
||||
@@ -1341,6 +1341,11 @@ describe("listSessionsFromStore subagent metadata", () => {
|
||||
sessionId: "sess-child",
|
||||
updatedAt: now - 1_000,
|
||||
spawnedBy: "agent:main:subagent:parent",
|
||||
spawnedWorkspaceDir: "/tmp/child-workspace",
|
||||
forkedFromParent: true,
|
||||
spawnDepth: 2,
|
||||
subagentRole: "orchestrator",
|
||||
subagentControlScope: "children",
|
||||
} as SessionEntry,
|
||||
"agent:main:subagent:failed": {
|
||||
sessionId: "sess-failed",
|
||||
@@ -1416,6 +1421,11 @@ describe("listSessionsFromStore subagent metadata", () => {
|
||||
expect(child?.startedAt).toBe(now - 7_500);
|
||||
expect(child?.endedAt).toBe(now - 2_500);
|
||||
expect(child?.runtimeMs).toBe(5_000);
|
||||
expect(child?.spawnedWorkspaceDir).toBe("/tmp/child-workspace");
|
||||
expect(child?.forkedFromParent).toBe(true);
|
||||
expect(child?.spawnDepth).toBe(2);
|
||||
expect(child?.subagentRole).toBe("orchestrator");
|
||||
expect(child?.subagentControlScope).toBe("children");
|
||||
expect(child?.childSessions).toBeUndefined();
|
||||
|
||||
const failed = result.sessions.find((session) => session.key === "agent:main:subagent:failed");
|
||||
|
||||
@@ -1194,6 +1194,11 @@ export function buildGatewaySessionRow(params: {
|
||||
return {
|
||||
key,
|
||||
spawnedBy: subagentOwner || entry?.spawnedBy,
|
||||
spawnedWorkspaceDir: entry?.spawnedWorkspaceDir,
|
||||
forkedFromParent: entry?.forkedFromParent,
|
||||
spawnDepth: entry?.spawnDepth,
|
||||
subagentRole: entry?.subagentRole,
|
||||
subagentControlScope: entry?.subagentControlScope,
|
||||
kind: classifySessionKey(key, entry),
|
||||
label: entry?.label,
|
||||
displayName,
|
||||
|
||||
@@ -18,6 +18,11 @@ export type SessionRunStatus = "running" | "done" | "failed" | "killed" | "timeo
|
||||
export type GatewaySessionRow = {
|
||||
key: string;
|
||||
spawnedBy?: string;
|
||||
spawnedWorkspaceDir?: string;
|
||||
forkedFromParent?: boolean;
|
||||
spawnDepth?: number;
|
||||
subagentRole?: SessionEntry["subagentRole"];
|
||||
subagentControlScope?: SessionEntry["subagentControlScope"];
|
||||
kind: "direct" | "group" | "global" | "unknown";
|
||||
label?: string;
|
||||
displayName?: string;
|
||||
|
||||
Reference in New Issue
Block a user