mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-02 02:50:20 +00:00
fix: enforce spawned session visibility in key resolve
This commit is contained in:
@@ -1116,6 +1116,41 @@ describe("gateway server sessions", () => {
|
||||
expect(resolved.payload?.key).toBe("agent:main:subagent:target");
|
||||
});
|
||||
|
||||
test("sessions.resolve by key respects spawnedBy visibility filters", async () => {
|
||||
await createSessionStoreDir();
|
||||
const now = Date.now();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"agent:main:subagent:visible-parent": {
|
||||
sessionId: "sess-visible-parent",
|
||||
updatedAt: now - 3_000,
|
||||
spawnedBy: "agent:main:main",
|
||||
},
|
||||
"agent:main:subagent:hidden-parent": {
|
||||
sessionId: "sess-hidden-parent",
|
||||
updatedAt: now - 2_000,
|
||||
spawnedBy: "agent:main:main",
|
||||
},
|
||||
"agent:main:subagent:shared-child-key-filter": {
|
||||
sessionId: "sess-shared-child-key-filter",
|
||||
updatedAt: now - 1_000,
|
||||
spawnedBy: "agent:main:subagent:hidden-parent",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { ws } = await openClient();
|
||||
const resolved = await rpcReq(ws, "sessions.resolve", {
|
||||
key: "agent:main:subagent:shared-child-key-filter",
|
||||
spawnedBy: "agent:main:subagent:visible-parent",
|
||||
});
|
||||
|
||||
expect(resolved.ok).toBe(false);
|
||||
expect(resolved.error?.message).toContain(
|
||||
"No session found: agent:main:subagent:shared-child-key-filter",
|
||||
);
|
||||
});
|
||||
|
||||
test("sessions.delete rejects main and aborts active runs", async () => {
|
||||
const { dir } = await createSessionStoreDir();
|
||||
await writeSingleLineSession(dir, "sess-main", "hello");
|
||||
|
||||
@@ -48,6 +48,25 @@ export async function resolveSessionKeyFromResolveParams(params: {
|
||||
const target = resolveGatewaySessionStoreTarget({ cfg, key });
|
||||
const store = loadSessionStore(target.storePath);
|
||||
if (store[target.canonicalKey]) {
|
||||
if (typeof p.spawnedBy === "string" && p.spawnedBy.trim().length > 0) {
|
||||
const visible = listSessionsFromStore({
|
||||
cfg,
|
||||
storePath: target.storePath,
|
||||
store,
|
||||
opts: {
|
||||
includeGlobal: p.includeGlobal === true,
|
||||
includeUnknown: p.includeUnknown === true,
|
||||
spawnedBy: p.spawnedBy,
|
||||
agentId: p.agentId,
|
||||
},
|
||||
}).sessions.some((session) => session.key === target.canonicalKey);
|
||||
if (!visible) {
|
||||
return {
|
||||
ok: false,
|
||||
error: errorShape(ErrorCodes.INVALID_REQUEST, `No session found: ${key}`),
|
||||
};
|
||||
}
|
||||
}
|
||||
return { ok: true, key: target.canonicalKey };
|
||||
}
|
||||
const legacyKey = target.storeKeys.find((candidate) => store[candidate]);
|
||||
@@ -63,6 +82,25 @@ export async function resolveSessionKeyFromResolveParams(params: {
|
||||
s[primaryKey] = s[legacyKey];
|
||||
}
|
||||
});
|
||||
if (typeof p.spawnedBy === "string" && p.spawnedBy.trim().length > 0) {
|
||||
const visible = listSessionsFromStore({
|
||||
cfg,
|
||||
storePath: target.storePath,
|
||||
store: loadSessionStore(target.storePath),
|
||||
opts: {
|
||||
includeGlobal: p.includeGlobal === true,
|
||||
includeUnknown: p.includeUnknown === true,
|
||||
spawnedBy: p.spawnedBy,
|
||||
agentId: p.agentId,
|
||||
},
|
||||
}).sessions.some((session) => session.key === target.canonicalKey);
|
||||
if (!visible) {
|
||||
return {
|
||||
ok: false,
|
||||
error: errorShape(ErrorCodes.INVALID_REQUEST, `No session found: ${key}`),
|
||||
};
|
||||
}
|
||||
}
|
||||
return { ok: true, key: target.canonicalKey };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user