openclaw/src/auto-reply/reply/commands-acp/context.test.ts

345 lines
12 KiB
TypeScript

import { beforeEach, describe, expect, it } from "vitest";
import {
__testing as feishuThreadBindingTesting,
createFeishuThreadBindingManager,
} from "../../../../extensions/feishu/src/thread-bindings.js";
import type { OpenClawConfig } from "../../../config/config.js";
import {
__testing as sessionBindingTesting,
getSessionBindingService,
} from "../../../infra/outbound/session-binding-service.js";
import { buildCommandTestParams } from "../commands-spawn.test-harness.js";
import {
isAcpCommandDiscordChannel,
resolveAcpCommandBindingContext,
resolveAcpCommandConversationId,
resolveAcpCommandParentConversationId,
} from "./context.js";
const baseCfg = {
session: { mainKey: "main", scope: "per-sender" },
} satisfies OpenClawConfig;
describe("commands-acp context", () => {
beforeEach(() => {
feishuThreadBindingTesting.resetFeishuThreadBindingsForTests();
sessionBindingTesting.resetSessionBindingAdaptersForTests();
});
it("resolves channel/account/thread context from originating fields", () => {
const params = buildCommandTestParams("/acp sessions", baseCfg, {
Provider: "discord",
Surface: "discord",
OriginatingChannel: "discord",
OriginatingTo: "channel:parent-1",
AccountId: "work",
MessageThreadId: "thread-42",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "discord",
accountId: "work",
threadId: "thread-42",
conversationId: "thread-42",
parentConversationId: "parent-1",
});
expect(isAcpCommandDiscordChannel(params)).toBe(true);
});
it("resolves discord thread parent from ParentSessionKey when targets point at the thread", () => {
const params = buildCommandTestParams("/acp sessions", baseCfg, {
Provider: "discord",
Surface: "discord",
OriginatingChannel: "discord",
OriginatingTo: "channel:thread-42",
AccountId: "work",
MessageThreadId: "thread-42",
ParentSessionKey: "agent:codex:discord:channel:parent-9",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "discord",
accountId: "work",
threadId: "thread-42",
conversationId: "thread-42",
parentConversationId: "parent-9",
});
});
it("resolves discord thread parent from native context when ParentSessionKey is absent", () => {
const params = buildCommandTestParams("/acp sessions", baseCfg, {
Provider: "discord",
Surface: "discord",
OriginatingChannel: "discord",
OriginatingTo: "channel:thread-42",
AccountId: "work",
MessageThreadId: "thread-42",
ThreadParentId: "parent-11",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "discord",
accountId: "work",
threadId: "thread-42",
conversationId: "thread-42",
parentConversationId: "parent-11",
});
});
it("falls back to default account and target-derived conversation id", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "slack",
Surface: "slack",
OriginatingChannel: "slack",
To: "<#123456789>",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "slack",
accountId: "default",
threadId: undefined,
conversationId: "123456789",
});
expect(resolveAcpCommandConversationId(params)).toBe("123456789");
expect(isAcpCommandDiscordChannel(params)).toBe(false);
});
it("builds canonical telegram topic conversation ids from originating chat + thread", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "telegram",
Surface: "telegram",
OriginatingChannel: "telegram",
OriginatingTo: "telegram:-1001234567890",
MessageThreadId: "42",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "telegram",
accountId: "default",
threadId: "42",
conversationId: "-1001234567890:topic:42",
parentConversationId: "-1001234567890",
});
expect(resolveAcpCommandConversationId(params)).toBe("-1001234567890:topic:42");
});
it("resolves Telegram DM conversation ids from telegram targets", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "telegram",
Surface: "telegram",
OriginatingChannel: "telegram",
OriginatingTo: "telegram:123456789",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "telegram",
accountId: "default",
threadId: undefined,
conversationId: "123456789",
parentConversationId: "123456789",
});
expect(resolveAcpCommandConversationId(params)).toBe("123456789");
});
it("resolves Matrix thread conversation ids from room targets", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "matrix-js",
Surface: "matrix-js",
OriginatingChannel: "matrix-js",
OriginatingTo: "room:!room:example",
MessageThreadId: "$thread-42",
AccountId: "work",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "matrix-js",
accountId: "work",
threadId: "$thread-42",
conversationId: "$thread-42",
parentConversationId: "!room:example",
});
expect(resolveAcpCommandConversationId(params)).toBe("$thread-42");
expect(resolveAcpCommandParentConversationId(params)).toBe("!room:example");
});
it("resolves Matrix room conversation ids outside thread context", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "matrix-js",
Surface: "matrix-js",
OriginatingChannel: "matrix-js",
OriginatingTo: "room:!room:example",
AccountId: "work",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "matrix-js",
accountId: "work",
threadId: undefined,
conversationId: "!room:example",
parentConversationId: "!room:example",
});
});
it("builds Feishu topic conversation ids from chat target + root message id", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "feishu",
Surface: "feishu",
OriginatingChannel: "feishu",
OriginatingTo: "chat:oc_group_chat",
MessageThreadId: "om_topic_root",
SenderId: "ou_topic_user",
AccountId: "work",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "feishu",
accountId: "work",
threadId: "om_topic_root",
conversationId: "oc_group_chat:topic:om_topic_root",
parentConversationId: "oc_group_chat",
});
expect(resolveAcpCommandConversationId(params)).toBe("oc_group_chat:topic:om_topic_root");
});
it("builds sender-scoped Feishu topic conversation ids when current session is sender-scoped", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "feishu",
Surface: "feishu",
OriginatingChannel: "feishu",
OriginatingTo: "chat:oc_group_chat",
MessageThreadId: "om_topic_root",
SenderId: "ou_topic_user",
AccountId: "work",
SessionKey: "agent:main:feishu:group:oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
});
params.sessionKey =
"agent:main:feishu:group:oc_group_chat:topic:om_topic_root:sender:ou_topic_user";
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "feishu",
accountId: "work",
threadId: "om_topic_root",
conversationId: "oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
parentConversationId: "oc_group_chat",
});
expect(resolveAcpCommandConversationId(params)).toBe(
"oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
);
});
it("preserves sender-scoped Feishu topic ids after ACP route takeover via ParentSessionKey", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "feishu",
Surface: "feishu",
OriginatingChannel: "feishu",
OriginatingTo: "chat:oc_group_chat",
MessageThreadId: "om_topic_root",
SenderId: "ou_topic_user",
AccountId: "work",
ParentSessionKey:
"agent:main:feishu:group:oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
});
params.sessionKey = "agent:codex:acp:binding:feishu:work:abc123";
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "feishu",
accountId: "work",
threadId: "om_topic_root",
conversationId: "oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
parentConversationId: "oc_group_chat",
});
});
it("preserves sender-scoped Feishu topic ids after ACP takeover from the live binding record", async () => {
createFeishuThreadBindingManager({ cfg: baseCfg, accountId: "work" });
await getSessionBindingService().bind({
targetSessionKey: "agent:codex:acp:binding:feishu:work:abc123",
targetKind: "session",
conversation: {
channel: "feishu",
accountId: "work",
conversationId: "oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
parentConversationId: "oc_group_chat",
},
placement: "current",
metadata: {
agentId: "codex",
},
});
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "feishu",
Surface: "feishu",
OriginatingChannel: "feishu",
OriginatingTo: "chat:oc_group_chat",
MessageThreadId: "om_topic_root",
SenderId: "ou_topic_user",
AccountId: "work",
});
params.sessionKey = "agent:codex:acp:binding:feishu:work:abc123";
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "feishu",
accountId: "work",
threadId: "om_topic_root",
conversationId: "oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
parentConversationId: "oc_group_chat",
});
});
it("resolves Feishu DM conversation ids from user targets", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "feishu",
Surface: "feishu",
OriginatingChannel: "feishu",
OriginatingTo: "user:ou_sender_1",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "feishu",
accountId: "default",
threadId: undefined,
conversationId: "ou_sender_1",
parentConversationId: undefined,
});
expect(resolveAcpCommandConversationId(params)).toBe("ou_sender_1");
});
it("resolves Feishu DM conversation ids from user_id fallback targets", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "feishu",
Surface: "feishu",
OriginatingChannel: "feishu",
OriginatingTo: "user:user_123",
});
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "feishu",
accountId: "default",
threadId: undefined,
conversationId: "user_123",
parentConversationId: undefined,
});
expect(resolveAcpCommandConversationId(params)).toBe("user_123");
});
it("does not infer a Feishu DM parent conversation id during fallback binding lookup", () => {
const params = buildCommandTestParams("/acp status", baseCfg, {
Provider: "feishu",
Surface: "feishu",
OriginatingChannel: "feishu",
OriginatingTo: "user:ou_sender_1",
AccountId: "work",
});
expect(resolveAcpCommandParentConversationId(params)).toBeUndefined();
expect(resolveAcpCommandBindingContext(params)).toEqual({
channel: "feishu",
accountId: "work",
threadId: undefined,
conversationId: "ou_sender_1",
parentConversationId: undefined,
});
});
});