mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-09 00:01:17 +00:00
fix: honor acp delivery default account
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createAcpDispatchDeliveryCoordinator } from "./dispatch-acp-delivery.js";
|
||||
import type { ReplyDispatcher } from "./reply-dispatcher.js";
|
||||
import { buildTestCtx } from "./test-ctx.js";
|
||||
@@ -11,10 +11,23 @@ const ttsMocks = vi.hoisted(() => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const deliveryMocks = vi.hoisted(() => ({
|
||||
routeReply: vi.fn(async (_params: unknown) => ({ ok: true, messageId: "mock-message" })),
|
||||
runMessageAction: vi.fn(async (_params: unknown) => ({ ok: true as const })),
|
||||
}));
|
||||
|
||||
vi.mock("../../tts/tts.js", () => ({
|
||||
maybeApplyTtsToPayload: (params: unknown) => ttsMocks.maybeApplyTtsToPayload(params),
|
||||
}));
|
||||
|
||||
vi.mock("./route-reply.js", () => ({
|
||||
routeReply: (params: unknown) => deliveryMocks.routeReply(params),
|
||||
}));
|
||||
|
||||
vi.mock("../../infra/outbound/message-action-runner.js", () => ({
|
||||
runMessageAction: (params: unknown) => deliveryMocks.runMessageAction(params),
|
||||
}));
|
||||
|
||||
function createDispatcher(): ReplyDispatcher {
|
||||
return {
|
||||
sendToolResult: vi.fn(() => true),
|
||||
@@ -43,6 +56,13 @@ function createCoordinator(onReplyStart?: (...args: unknown[]) => Promise<void>)
|
||||
}
|
||||
|
||||
describe("createAcpDispatchDeliveryCoordinator", () => {
|
||||
beforeEach(() => {
|
||||
deliveryMocks.routeReply.mockClear();
|
||||
deliveryMocks.routeReply.mockResolvedValue({ ok: true, messageId: "mock-message" });
|
||||
deliveryMocks.runMessageAction.mockClear();
|
||||
deliveryMocks.runMessageAction.mockResolvedValue({ ok: true as const });
|
||||
});
|
||||
|
||||
it("bypasses TTS when skipTts is requested", async () => {
|
||||
const dispatcher = createDispatcher();
|
||||
const coordinator = createAcpDispatchDeliveryCoordinator({
|
||||
@@ -221,4 +241,36 @@ describe("createAcpDispatchDeliveryCoordinator", () => {
|
||||
expect(coordinator.getAccumulatedBlockText()).toBe("working on it");
|
||||
expect(coordinator.hasDeliveredVisibleText()).toBe(false);
|
||||
});
|
||||
|
||||
it("routes ACP replies through the configured default account when AccountId is omitted", async () => {
|
||||
const coordinator = createAcpDispatchDeliveryCoordinator({
|
||||
cfg: createAcpTestConfig({
|
||||
channels: {
|
||||
discord: {
|
||||
defaultAccount: "work",
|
||||
},
|
||||
},
|
||||
}),
|
||||
ctx: buildTestCtx({
|
||||
Provider: "discord",
|
||||
Surface: "discord",
|
||||
SessionKey: "agent:codex-acp:session-1",
|
||||
}),
|
||||
dispatcher: createDispatcher(),
|
||||
inboundAudio: false,
|
||||
shouldRouteToOriginating: true,
|
||||
originatingChannel: "discord",
|
||||
originatingTo: "channel:thread-1",
|
||||
});
|
||||
|
||||
await coordinator.deliver("block", { text: "hello" }, { skipTts: true });
|
||||
|
||||
expect(deliveryMocks.routeReply).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
channel: "discord",
|
||||
to: "channel:thread-1",
|
||||
accountId: "work",
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +29,28 @@ function normalizeDeliveryChannel(value: string | undefined): string | undefined
|
||||
return normalized || undefined;
|
||||
}
|
||||
|
||||
function resolveDeliveryAccountId(params: {
|
||||
cfg: OpenClawConfig;
|
||||
channel: string | undefined;
|
||||
accountId: string | undefined;
|
||||
}): string | undefined {
|
||||
const explicit = params.accountId?.trim();
|
||||
if (explicit) {
|
||||
return explicit;
|
||||
}
|
||||
const channelId = normalizeDeliveryChannel(params.channel);
|
||||
if (!channelId) {
|
||||
return undefined;
|
||||
}
|
||||
const channelCfg = (params.cfg.channels as Record<string, { defaultAccount?: unknown } | undefined>)[
|
||||
channelId
|
||||
];
|
||||
const configuredDefault = channelCfg?.defaultAccount;
|
||||
return typeof configuredDefault === "string" && configuredDefault.trim()
|
||||
? configuredDefault.trim()
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function shouldTreatDeliveredTextAsVisible(params: {
|
||||
channel: string | undefined;
|
||||
kind: ReplyDispatchKind;
|
||||
@@ -113,6 +135,11 @@ export function createAcpDispatchDeliveryCoordinator(params: {
|
||||
};
|
||||
const directChannel = normalizeDeliveryChannel(params.ctx.Provider ?? params.ctx.Surface);
|
||||
const routedChannel = normalizeDeliveryChannel(params.originatingChannel);
|
||||
const resolvedAccountId = resolveDeliveryAccountId({
|
||||
cfg: params.cfg,
|
||||
channel: routedChannel ?? directChannel,
|
||||
accountId: params.ctx.AccountId,
|
||||
});
|
||||
|
||||
const settleDirectVisibleText = async () => {
|
||||
if (state.settledDirectVisibleText || state.queuedDirectVisibleTextDeliveries === 0) {
|
||||
@@ -229,7 +256,7 @@ export function createAcpDispatchDeliveryCoordinator(params: {
|
||||
channel: params.originatingChannel,
|
||||
to: params.originatingTo,
|
||||
sessionKey: params.ctx.SessionKey,
|
||||
accountId: params.ctx.AccountId,
|
||||
accountId: resolvedAccountId,
|
||||
threadId: params.ctx.MessageThreadId,
|
||||
cfg: params.cfg,
|
||||
});
|
||||
@@ -245,7 +272,7 @@ export function createAcpDispatchDeliveryCoordinator(params: {
|
||||
if (kind === "tool" && meta?.toolCallId && result.messageId) {
|
||||
state.toolMessageByCallId.set(meta.toolCallId, {
|
||||
channel: params.originatingChannel,
|
||||
accountId: params.ctx.AccountId,
|
||||
accountId: resolvedAccountId,
|
||||
to: params.originatingTo,
|
||||
...(params.ctx.MessageThreadId != null ? { threadId: params.ctx.MessageThreadId } : {}),
|
||||
messageId: result.messageId,
|
||||
|
||||
Reference in New Issue
Block a user