mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-23 22:55:24 +00:00
Gateway: allow control-ui session deletion
This commit is contained in:
@@ -77,6 +77,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Dashboard/Sessions: allow authenticated Control UI clients to delete and patch sessions while still blocking regular webchat clients from session mutation RPCs, fixing Dashboard session delete failures. (#21264) Thanks @jskoiz.
|
||||
- Podman/Quadlet setup: fix `sed` escaping and UID mismatch in Podman Quadlet setup. (#26414) Thanks @KnHack and @vincentkoc.
|
||||
- Browser/Navigate: resolve the correct `targetId` in navigate responses after renderer swaps. (#25326) Thanks @stone-jin and @vincentkoc.
|
||||
- Agents/Ollama discovery: skip Ollama discovery when explicit models are configured. (#28827) Thanks @Kansodata and @vincentkoc.
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
normalizeAgentId,
|
||||
parseAgentSessionKey,
|
||||
} from "../../routing/session-key.js";
|
||||
import { GATEWAY_CLIENT_IDS } from "../protocol/client-info.js";
|
||||
import {
|
||||
ErrorCodes,
|
||||
errorShape,
|
||||
@@ -86,6 +87,9 @@ function rejectWebchatSessionMutation(params: {
|
||||
if (!params.client?.connect || !params.isWebchatConnect(params.client.connect)) {
|
||||
return false;
|
||||
}
|
||||
if (params.client.connect.client.id === GATEWAY_CLIENT_IDS.CONTROL_UI) {
|
||||
return false;
|
||||
}
|
||||
params.respond(
|
||||
false,
|
||||
undefined,
|
||||
|
||||
@@ -1234,4 +1234,52 @@ describe("gateway server sessions", () => {
|
||||
|
||||
ws.close();
|
||||
});
|
||||
|
||||
test("control-ui client can delete sessions even in webchat mode", async () => {
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-sessions-control-ui-delete-"));
|
||||
const storePath = path.join(dir, "sessions.json");
|
||||
testState.sessionStorePath = storePath;
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"discord:group:dev": {
|
||||
sessionId: "sess-group",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const ws = new WebSocket(`ws://127.0.0.1:${harness.port}`, {
|
||||
headers: { origin: `http://127.0.0.1:${harness.port}` },
|
||||
});
|
||||
trackConnectChallengeNonce(ws);
|
||||
await new Promise<void>((resolve) => ws.once("open", resolve));
|
||||
await connectOk(ws, {
|
||||
client: {
|
||||
id: GATEWAY_CLIENT_IDS.CONTROL_UI,
|
||||
version: "1.0.0",
|
||||
platform: "test",
|
||||
mode: GATEWAY_CLIENT_MODES.WEBCHAT,
|
||||
},
|
||||
scopes: ["operator.admin"],
|
||||
});
|
||||
|
||||
const deleted = await rpcReq<{ ok: true; deleted: boolean }>(ws, "sessions.delete", {
|
||||
key: "agent:main:discord:group:dev",
|
||||
});
|
||||
expect(deleted.ok).toBe(true);
|
||||
expect(deleted.payload?.deleted).toBe(true);
|
||||
|
||||
const store = JSON.parse(await fs.readFile(storePath, "utf-8")) as Record<
|
||||
string,
|
||||
{ sessionId?: string }
|
||||
>;
|
||||
expect(store["agent:main:discord:group:dev"]).toBeUndefined();
|
||||
|
||||
ws.close();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user