fix: preserve account routing for explicit targets
Co-authored-by: adam91holt <adam91holt@users.noreply.github.com>
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
|
||||
### Fixes
|
||||
- Sub-agents: normalize announce delivery origin + queue bucketing by accountId to keep multi-account routing stable. (#1061, #1058) — thanks @adam91holt.
|
||||
- Gateway: honor explicit delivery targets without implicit accountId fallback; preserve lastAccountId for implicit routing.
|
||||
- Repo: fix oxlint config filename and move ignore pattern into config. (#1064) — thanks @connorshea.
|
||||
- Messages: `/stop` now hard-aborts queued followups and sub-agent runs; suppress zero-count stop notes.
|
||||
- Sessions: reset `compactionCount` on `/new` and `/reset`, and preserve `sessions.json` file mode (0600).
|
||||
|
||||
@@ -155,6 +155,7 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
skillsSnapshot: entry?.skillsSnapshot,
|
||||
lastChannel: entry?.lastChannel,
|
||||
lastTo: entry?.lastTo,
|
||||
lastAccountId: entry?.lastAccountId,
|
||||
modelOverride: entry?.modelOverride,
|
||||
providerOverride: entry?.providerOverride,
|
||||
label: labelValue,
|
||||
@@ -201,8 +202,11 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
|
||||
const lastChannel = sessionEntry?.lastChannel;
|
||||
const lastTo = typeof sessionEntry?.lastTo === "string" ? sessionEntry.lastTo.trim() : "";
|
||||
const explicitTo =
|
||||
typeof request.to === "string" && request.to.trim() ? request.to.trim() : undefined;
|
||||
const resolvedAccountId =
|
||||
normalizeAccountId(request.accountId) ?? normalizeAccountId(sessionEntry?.lastAccountId);
|
||||
normalizeAccountId(request.accountId) ??
|
||||
(explicitTo ? undefined : normalizeAccountId(sessionEntry?.lastAccountId));
|
||||
|
||||
const wantsDelivery = request.deliver === true;
|
||||
|
||||
@@ -224,8 +228,6 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
return wantsDelivery ? DEFAULT_CHAT_CHANNEL : INTERNAL_MESSAGE_CHANNEL;
|
||||
})();
|
||||
|
||||
const explicitTo =
|
||||
typeof request.to === "string" && request.to.trim() ? request.to.trim() : undefined;
|
||||
const deliveryTargetMode = explicitTo
|
||||
? "explicit"
|
||||
: isDeliverableMessageChannel(resolvedChannel)
|
||||
|
||||
@@ -152,6 +152,95 @@ describe("gateway server agent", () => {
|
||||
testState.allowFrom = undefined;
|
||||
});
|
||||
|
||||
test("agent avoids lastAccountId when explicit to is provided", async () => {
|
||||
testState.allowFrom = ["+1555"];
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
||||
testState.sessionStorePath = path.join(dir, "sessions.json");
|
||||
await fs.writeFile(
|
||||
testState.sessionStorePath,
|
||||
JSON.stringify(
|
||||
{
|
||||
main: {
|
||||
sessionId: "sess-main-explicit",
|
||||
updatedAt: Date.now(),
|
||||
lastChannel: "whatsapp",
|
||||
lastTo: "+1555",
|
||||
lastAccountId: "legacy",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const { server, ws } = await startServerWithClient();
|
||||
await connectOk(ws);
|
||||
|
||||
const res = await rpcReq(ws, "agent", {
|
||||
message: "hi",
|
||||
sessionKey: "main",
|
||||
deliver: true,
|
||||
to: "+1666",
|
||||
idempotencyKey: "idem-agent-explicit",
|
||||
});
|
||||
expect(res.ok).toBe(true);
|
||||
|
||||
const spy = vi.mocked(agentCommand);
|
||||
const call = spy.mock.calls.at(-1)?.[0] as Record<string, unknown>;
|
||||
expectChannels(call, "whatsapp");
|
||||
expect(call.to).toBe("+1666");
|
||||
expect(call.accountId).toBeUndefined();
|
||||
|
||||
ws.close();
|
||||
await server.close();
|
||||
testState.allowFrom = undefined;
|
||||
});
|
||||
|
||||
test("agent falls back to lastAccountId for implicit delivery", async () => {
|
||||
testState.allowFrom = ["+1555"];
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
||||
testState.sessionStorePath = path.join(dir, "sessions.json");
|
||||
await fs.writeFile(
|
||||
testState.sessionStorePath,
|
||||
JSON.stringify(
|
||||
{
|
||||
main: {
|
||||
sessionId: "sess-main-implicit",
|
||||
updatedAt: Date.now(),
|
||||
lastChannel: "whatsapp",
|
||||
lastTo: "+1555",
|
||||
lastAccountId: "kev",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const { server, ws } = await startServerWithClient();
|
||||
await connectOk(ws);
|
||||
|
||||
const res = await rpcReq(ws, "agent", {
|
||||
message: "hi",
|
||||
sessionKey: "main",
|
||||
deliver: true,
|
||||
idempotencyKey: "idem-agent-implicit-account",
|
||||
});
|
||||
expect(res.ok).toBe(true);
|
||||
|
||||
const spy = vi.mocked(agentCommand);
|
||||
const call = spy.mock.calls.at(-1)?.[0] as Record<string, unknown>;
|
||||
expectChannels(call, "whatsapp");
|
||||
expect(call.to).toBe("+1555");
|
||||
expect(call.accountId).toBe("kev");
|
||||
|
||||
ws.close();
|
||||
await server.close();
|
||||
testState.allowFrom = undefined;
|
||||
});
|
||||
|
||||
test("agent forwards image attachments as images[]", async () => {
|
||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
|
||||
testState.sessionStorePath = path.join(dir, "sessions.json");
|
||||
|
||||
Reference in New Issue
Block a user