mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-11 01:01:13 +00:00
fix: honor default account in conversation bindings
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../config/config.js";
|
||||
import {
|
||||
__testing as sessionBindingTesting,
|
||||
@@ -425,6 +425,10 @@ describe("commands-acp context", () => {
|
||||
sessionBindingTesting.resetSessionBindingAdaptersForTests();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
setMinimalAcpContextRegistryForTests();
|
||||
});
|
||||
|
||||
it("resolves channel/account/thread context from originating fields", () => {
|
||||
const params = buildCommandTestParams("/acp sessions", baseCfg, {
|
||||
Provider: "discord",
|
||||
@@ -501,6 +505,58 @@ describe("commands-acp context", () => {
|
||||
expect(resolveAcpCommandConversationId(params)).toBe("123456789");
|
||||
});
|
||||
|
||||
it("uses the plugin default account when ACP context omits AccountId", () => {
|
||||
setActivePluginRegistry(
|
||||
createTestRegistry([
|
||||
{
|
||||
pluginId: "line",
|
||||
source: "test",
|
||||
plugin: {
|
||||
...createChannelTestPluginBase({
|
||||
id: "line",
|
||||
label: "LINE",
|
||||
config: {
|
||||
listAccountIds: () => ["default", "work"],
|
||||
defaultAccountId: () => "work",
|
||||
},
|
||||
}),
|
||||
bindings: {
|
||||
resolveCommandConversation: ({
|
||||
originatingTo,
|
||||
commandTo,
|
||||
fallbackTo,
|
||||
}: {
|
||||
originatingTo?: string;
|
||||
commandTo?: string;
|
||||
fallbackTo?: string;
|
||||
}) => {
|
||||
const conversationId =
|
||||
parseLineConversationIdFromTargetForTest(originatingTo) ??
|
||||
parseLineConversationIdFromTargetForTest(commandTo) ??
|
||||
parseLineConversationIdFromTargetForTest(fallbackTo);
|
||||
return conversationId ? { conversationId } : null;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const params = buildCommandTestParams("/acp status", baseCfg, {
|
||||
Provider: "line",
|
||||
Surface: "line",
|
||||
OriginatingChannel: "line",
|
||||
OriginatingTo: "line:user:U1234567890abcdef1234567890abcdef",
|
||||
});
|
||||
|
||||
expect(resolveAcpCommandBindingContext(params)).toEqual({
|
||||
channel: "line",
|
||||
accountId: "work",
|
||||
threadId: undefined,
|
||||
conversationId: "U1234567890abcdef1234567890abcdef",
|
||||
});
|
||||
});
|
||||
|
||||
it("builds canonical telegram topic conversation ids from originating chat + thread", () => {
|
||||
const params = buildCommandTestParams("/acp status", baseCfg, {
|
||||
Provider: "telegram",
|
||||
|
||||
@@ -13,7 +13,11 @@ export function resolveAcpCommandChannel(params: HandleCommandsParams): string {
|
||||
}
|
||||
|
||||
export function resolveAcpCommandAccountId(params: HandleCommandsParams): string {
|
||||
return resolveConversationBindingAccountIdFromMessage(params.ctx);
|
||||
return resolveConversationBindingAccountIdFromMessage({
|
||||
ctx: params.ctx,
|
||||
cfg: params.cfg,
|
||||
commandChannel: params.command.channel,
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveAcpCommandThreadId(params: HandleCommandsParams): string | undefined {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { normalizeConversationText } from "../../acp/conversation-id.js";
|
||||
import { resolveConversationBindingContext } from "../../channels/conversation-binding-context.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { getActivePluginChannelRegistry } from "../../plugins/runtime.js";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import type { HandleCommandsParams } from "./commands-types.js";
|
||||
|
||||
@@ -27,9 +28,21 @@ function resolveBindingChannel(ctx: BindingMsgContext, commandChannel?: string |
|
||||
return normalizeConversationText(raw).toLowerCase();
|
||||
}
|
||||
|
||||
function resolveBindingAccountId(ctx: BindingMsgContext): string {
|
||||
const accountId = normalizeConversationText(ctx.AccountId);
|
||||
return accountId || "default";
|
||||
function resolveBindingAccountId(params: {
|
||||
ctx: BindingMsgContext;
|
||||
cfg: OpenClawConfig;
|
||||
commandChannel?: string | null;
|
||||
}): string {
|
||||
const channel = resolveBindingChannel(params.ctx, params.commandChannel);
|
||||
const plugin = getActivePluginChannelRegistry()?.channels.find(
|
||||
(entry) => entry.plugin.id === channel,
|
||||
)?.plugin;
|
||||
const accountId = normalizeConversationText(params.ctx.AccountId);
|
||||
return (
|
||||
accountId ||
|
||||
normalizeConversationText(plugin?.config.defaultAccountId?.(params.cfg)) ||
|
||||
"default"
|
||||
);
|
||||
}
|
||||
|
||||
function resolveBindingThreadId(threadId: string | number | null | undefined): string | undefined {
|
||||
@@ -45,10 +58,15 @@ export function resolveConversationBindingContextFromMessage(params: {
|
||||
parentSessionKey?: string | null;
|
||||
commandTo?: string | null;
|
||||
}): ReturnType<typeof resolveConversationBindingContext> {
|
||||
const channel = resolveBindingChannel(params.ctx);
|
||||
return resolveConversationBindingContext({
|
||||
cfg: params.cfg,
|
||||
channel: resolveBindingChannel(params.ctx),
|
||||
accountId: resolveBindingAccountId(params.ctx),
|
||||
channel,
|
||||
accountId: resolveBindingAccountId({
|
||||
ctx: params.ctx,
|
||||
cfg: params.cfg,
|
||||
commandChannel: channel,
|
||||
}),
|
||||
chatType: params.ctx.ChatType,
|
||||
threadId: resolveBindingThreadId(params.ctx.MessageThreadId),
|
||||
threadParentId: params.ctx.ThreadParentId,
|
||||
@@ -83,8 +101,12 @@ export function resolveConversationBindingChannelFromMessage(
|
||||
return resolveBindingChannel(ctx, commandChannel);
|
||||
}
|
||||
|
||||
export function resolveConversationBindingAccountIdFromMessage(ctx: BindingMsgContext): string {
|
||||
return resolveBindingAccountId(ctx);
|
||||
export function resolveConversationBindingAccountIdFromMessage(params: {
|
||||
ctx: BindingMsgContext;
|
||||
cfg: OpenClawConfig;
|
||||
commandChannel?: string | null;
|
||||
}): string {
|
||||
return resolveBindingAccountId(params);
|
||||
}
|
||||
|
||||
export function resolveConversationBindingThreadIdFromMessage(
|
||||
|
||||
61
src/channels/conversation-binding-context.test.ts
Normal file
61
src/channels/conversation-binding-context.test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
import { resolveConversationBindingContext } from "./conversation-binding-context.js";
|
||||
|
||||
describe("resolveConversationBindingContext", () => {
|
||||
afterEach(() => {
|
||||
setActivePluginRegistry(createTestRegistry());
|
||||
});
|
||||
|
||||
it("uses the plugin default account when accountId is omitted", () => {
|
||||
setActivePluginRegistry(
|
||||
createTestRegistry([
|
||||
{
|
||||
pluginId: "line",
|
||||
source: "test",
|
||||
plugin: {
|
||||
...createChannelTestPluginBase({
|
||||
id: "line",
|
||||
label: "LINE",
|
||||
config: {
|
||||
listAccountIds: () => ["default", "work"],
|
||||
defaultAccountId: () => "work",
|
||||
},
|
||||
}),
|
||||
bindings: {
|
||||
resolveCommandConversation: ({
|
||||
originatingTo,
|
||||
commandTo,
|
||||
fallbackTo,
|
||||
}: {
|
||||
originatingTo?: string;
|
||||
commandTo?: string;
|
||||
fallbackTo?: string;
|
||||
}) => {
|
||||
const conversationId = [originatingTo, commandTo, fallbackTo]
|
||||
.map((candidate) => candidate?.trim().replace(/^line:/i, ""))
|
||||
.map((candidate) => candidate?.replace(/^user:/i, ""))
|
||||
.find((candidate) => candidate && candidate.length > 0);
|
||||
return conversationId ? { conversationId } : null;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
resolveConversationBindingContext({
|
||||
cfg: {} as OpenClawConfig,
|
||||
channel: "line",
|
||||
originatingTo: "line:user:U1234567890abcdef1234567890abcdef",
|
||||
}),
|
||||
).toEqual({
|
||||
channel: "line",
|
||||
accountId: "work",
|
||||
conversationId: "U1234567890abcdef1234567890abcdef",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -59,6 +59,18 @@ function shouldDefaultParentConversationToSelf(plugin?: ChannelPlugin): boolean
|
||||
return plugin?.bindings?.selfParentConversationByDefault === true;
|
||||
}
|
||||
|
||||
function resolveBindingAccountId(params: {
|
||||
rawAccountId?: string | null;
|
||||
plugin?: ChannelPlugin;
|
||||
cfg: OpenClawConfig;
|
||||
}): string {
|
||||
return (
|
||||
normalizeText(params.rawAccountId) ||
|
||||
normalizeText(params.plugin?.config.defaultAccountId?.(params.cfg)) ||
|
||||
"default"
|
||||
);
|
||||
}
|
||||
|
||||
function resolveChannelTargetId(params: {
|
||||
channel: string;
|
||||
target?: string | null;
|
||||
@@ -124,9 +136,13 @@ export function resolveConversationBindingContext(
|
||||
if (!channel) {
|
||||
return null;
|
||||
}
|
||||
const accountId = normalizeText(params.accountId) || "default";
|
||||
const threadId = normalizeText(params.threadId != null ? String(params.threadId) : undefined);
|
||||
const loadedPlugin = getLoadedChannelPlugin(channel);
|
||||
const accountId = resolveBindingAccountId({
|
||||
rawAccountId: params.accountId,
|
||||
plugin: loadedPlugin,
|
||||
cfg: params.cfg,
|
||||
});
|
||||
const threadId = normalizeText(params.threadId != null ? String(params.threadId) : undefined);
|
||||
|
||||
const resolvedByProvider = loadedPlugin?.bindings?.resolveCommandConversation?.({
|
||||
accountId,
|
||||
|
||||
Reference in New Issue
Block a user