mirror of https://github.com/openclaw/openclaw.git
Gateway: reject delivered inter_session sentinel
This commit is contained in:
parent
7e38aee263
commit
d32cd5340e
|
|
@ -1,5 +1,6 @@
|
|||
import { describe, expect, it, vi } from "vitest";
|
||||
import { BARE_SESSION_RESET_PROMPT } from "../../auto-reply/reply/session-reset-prompt.js";
|
||||
import * as channelSelection from "../../infra/outbound/channel-selection.js";
|
||||
import { agentHandlers } from "./agent.js";
|
||||
import type { GatewayRequestContext } from "./types.js";
|
||||
|
||||
|
|
@ -477,6 +478,55 @@ describe("gateway agent handler", () => {
|
|||
expect(callArgs?.runContext?.messageChannel).toBe("inter_session");
|
||||
});
|
||||
|
||||
it("rejects deliver=true when backend callers use the inter_session sentinel", async () => {
|
||||
primeMainAgentRun();
|
||||
mocks.agentCommand.mockClear();
|
||||
const selectionSpy = vi.spyOn(channelSelection, "resolveMessageChannelSelection");
|
||||
selectionSpy.mockResolvedValue({
|
||||
channel: "telegram",
|
||||
configured: ["telegram"],
|
||||
source: "single-configured",
|
||||
});
|
||||
|
||||
const respond = await invokeAgent(
|
||||
{
|
||||
message: "strict delivery",
|
||||
agentId: "main",
|
||||
sessionKey: "agent:main:main",
|
||||
channel: "inter_session",
|
||||
deliver: true,
|
||||
idempotencyKey: "test-inter-session-backend-deliver",
|
||||
},
|
||||
{
|
||||
reqId: "inter-session-backend-deliver-1",
|
||||
client: {
|
||||
connect: {
|
||||
role: "operator",
|
||||
scopes: ["operator.write"],
|
||||
client: {
|
||||
id: "gateway-client",
|
||||
mode: "backend",
|
||||
version: "1.0.0",
|
||||
platform: "node",
|
||||
},
|
||||
},
|
||||
} as unknown as AgentHandlerArgs["client"],
|
||||
},
|
||||
);
|
||||
|
||||
selectionSpy.mockRestore();
|
||||
|
||||
expect(respond).toHaveBeenCalledTimes(1);
|
||||
const [ok, payload, error] = respond.mock.calls[0] ?? [];
|
||||
expect(ok).toBe(false);
|
||||
expect(payload).toBeUndefined();
|
||||
expect(error).toMatchObject({
|
||||
code: "INVALID_REQUEST",
|
||||
message: expect.stringContaining("inter_session"),
|
||||
});
|
||||
expect(mocks.agentCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("only forwards workspaceDir for spawned subagent runs", async () => {
|
||||
primeMainAgentRun();
|
||||
mocks.agentCommand.mockClear();
|
||||
|
|
|
|||
|
|
@ -481,6 +481,20 @@ export const agentHandlers: GatewayRequestHandlers = {
|
|||
}
|
||||
|
||||
const wantsDelivery = request.deliver === true;
|
||||
const requestedInterSessionForDelivery = [request.channel, request.replyChannel].some((value) =>
|
||||
isInterSessionChannel(normalizeMessageChannel(value)),
|
||||
);
|
||||
if (wantsDelivery && requestedInterSessionForDelivery) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
"delivery channel cannot use the inter_session sentinel",
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
const explicitTo =
|
||||
typeof request.replyTo === "string" && request.replyTo.trim()
|
||||
? request.replyTo.trim()
|
||||
|
|
|
|||
|
|
@ -88,9 +88,10 @@ export function resolveAgentDeliveryPlan(params: {
|
|||
});
|
||||
|
||||
const resolvedChannel = (() => {
|
||||
// Hard-reject internal sentinel channels. INTER_SESSION_CHANNEL is excluded
|
||||
// from listGatewayMessageChannels() so external callers are already blocked,
|
||||
// but defend here too in case the channel reaches delivery via another path.
|
||||
// Internal sentinels must never resolve to a deliverable channel. Keep
|
||||
// them on the internal/webchat path here so non-delivery flows stay
|
||||
// internal; callers that request real delivery must reject sentinels
|
||||
// before reaching this planner.
|
||||
if (
|
||||
requestedChannel &&
|
||||
RESERVED_CHANNEL_IDS.has(requestedChannel.toLowerCase()) &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue