fix: omit live deliveryContext when targeting a remote gateway
resolveGatewayWriteMeta() was forwarding the local agent run's deliveryContext to config.apply/config.patch/update.run even when gatewayUrl pointed to a remote gateway. Server handlers now prefer params.deliveryContext over extractDeliveryInfo(sessionKey), so a remote restart sentinel would be written with the local chat's channel/ to, causing post-restart wake messages to be delivered to the caller's chat instead of the session that lives on the remote gateway. Fix: gate deliveryContext forwarding on isRemoteGateway (truthy gatewayOpts.gatewayUrl). When targeting a remote gateway, omit deliveryContext so the remote server's extractDeliveryInfo(sessionKey) remains authoritative for the routing of that session. See #18612.
This commit is contained in:
parent
80538c607d
commit
33c24858ff
@ -168,6 +168,31 @@ describe("createGatewayTool – live delivery context guard", () => {
|
||||
expect(sentinelPayload?.deliveryContext?.to).toBe("123456789");
|
||||
});
|
||||
|
||||
it("does not forward live RPC delivery context when gatewayUrl targets a remote gateway", async () => {
|
||||
// A remote gateway has its own extractDeliveryInfo(sessionKey) — forwarding
|
||||
// the local agent's deliveryContext would write a sentinel with the wrong
|
||||
// destination on the remote host.
|
||||
mocks.callGatewayTool.mockClear();
|
||||
mocks.readGatewayCallOptions.mockReturnValueOnce({ gatewayUrl: "wss://remote-gw.example.com" });
|
||||
const tool = createGatewayTool({
|
||||
agentSessionKey: "agent:main:main",
|
||||
agentChannel: "discord",
|
||||
agentTo: "123456789",
|
||||
});
|
||||
|
||||
await execTool(tool, {
|
||||
action: "config.patch",
|
||||
raw: '{"key":"value"}',
|
||||
baseHash: "abc123",
|
||||
sessionKey: "agent:main:main",
|
||||
note: "remote patch",
|
||||
gatewayUrl: "wss://remote-gw.example.com",
|
||||
});
|
||||
|
||||
const forwardedParams = getCallArg<Record<string, unknown>>(mocks.callGatewayTool, 0, 2);
|
||||
expect(forwardedParams?.deliveryContext).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not forward live RPC delivery context when a non-default agent passes sessionKey='main'", async () => {
|
||||
// "main" resolves to "agent:main:main" (default agent), which differs from the
|
||||
// current session "agent:shopping-claw:main". Live context must NOT be forwarded.
|
||||
|
||||
@ -268,7 +268,15 @@ export function createGatewayTool(opts?: {
|
||||
explicitSessionKey != null &&
|
||||
rpcCanonicalizeTarget(explicitSessionKey) !==
|
||||
(rpcOwnKey ? rpcCanonicalizeOwn(rpcOwnKey) : undefined);
|
||||
const deliveryContext = isTargetingOtherSession ? undefined : liveDeliveryContextForRpc;
|
||||
// Also omit when the call targets a remote gateway. The remote server's
|
||||
// extractDeliveryInfo(sessionKey) is the authoritative source for that
|
||||
// session's delivery route. Forwarding the local agent run's deliveryContext
|
||||
// would write a sentinel with the wrong chat destination on the remote host,
|
||||
// causing post-restart wake messages to be sent to the caller's chat instead
|
||||
// of the session on the remote gateway. See #18612.
|
||||
const isRemoteGateway = Boolean(gatewayOpts.gatewayUrl?.trim());
|
||||
const deliveryContext =
|
||||
isTargetingOtherSession || isRemoteGateway ? undefined : liveDeliveryContextForRpc;
|
||||
return { sessionKey, note, restartDelayMs, deliveryContext };
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user