Fix: move bootstrap session grammar into plugin-owned session-key surfaces (#58400)

Merged via squash.

Prepared head SHA: b062b18b03
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
Gustavo Madeira Santana
2026-03-31 19:41:01 -04:00
committed by GitHub
parent bf0f33db32
commit bea53d7a3f
38 changed files with 1082 additions and 288 deletions

View File

@@ -183,6 +183,46 @@ describe("feishuPlugin.pairing.notifyApproval", () => {
});
});
describe("feishuPlugin messaging", () => {
beforeEach(async () => {
vi.resetModules();
({ feishuPlugin } = await import("./channel.js"));
});
it("owns sender/topic session inheritance candidates", () => {
expect(
feishuPlugin.messaging?.resolveSessionConversation?.({
kind: "group",
rawId: "oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
}),
).toEqual({
id: "oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
baseConversationId: "oc_group_chat",
parentConversationCandidates: ["oc_group_chat:topic:om_topic_root", "oc_group_chat"],
});
expect(
feishuPlugin.messaging?.resolveSessionConversation?.({
kind: "group",
rawId: "oc_group_chat:topic:om_topic_root",
}),
).toEqual({
id: "oc_group_chat:topic:om_topic_root",
baseConversationId: "oc_group_chat",
parentConversationCandidates: ["oc_group_chat"],
});
expect(
feishuPlugin.messaging?.resolveSessionConversation?.({
kind: "group",
rawId: "oc_group_chat:Topic:om_topic_root:Sender:ou_topic_user",
}),
).toEqual({
id: "oc_group_chat:topic:om_topic_root:sender:ou_topic_user",
baseConversationId: "oc_group_chat",
parentConversationCandidates: ["oc_group_chat:topic:om_topic_root", "oc_group_chat"],
});
});
});
describe("feishuPlugin actions", () => {
const cfg = {
channels: {

View File

@@ -55,6 +55,10 @@ import {
import { listFeishuDirectoryPeers, listFeishuDirectoryGroups } from "./directory.static.js";
import { resolveFeishuGroupToolPolicy } from "./policy.js";
import { getFeishuRuntime } from "./runtime.js";
import {
resolveFeishuParentConversationCandidates,
resolveFeishuSessionConversation,
} from "./session-conversation.js";
import { resolveFeishuOutboundSessionRoute } from "./session-route.js";
import { feishuSetupAdapter } from "./setup-core.js";
import { feishuSetupWizard } from "./setup-surface.js";
@@ -1068,6 +1072,8 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount, FeishuProbeResul
setupWizard: feishuSetupWizard,
messaging: {
normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? undefined,
resolveSessionConversation: ({ kind, rawId }) =>
resolveFeishuSessionConversation({ kind, rawId }),
resolveOutboundSessionRoute: (params) => resolveFeishuOutboundSessionRoute(params),
targetResolver: {
looksLikeId: looksLikeFeishuId,

View File

@@ -100,7 +100,7 @@ export function parseFeishuConversationId(params: {
return null;
}
const topicSenderMatch = conversationId.match(/^(.+):topic:([^:]+):sender:([^:]+)$/);
const topicSenderMatch = conversationId.match(/^(.+):topic:([^:]+):sender:([^:]+)$/i);
if (topicSenderMatch) {
const [, chatId, topicId, senderOpenId] = topicSenderMatch;
return {
@@ -117,7 +117,7 @@ export function parseFeishuConversationId(params: {
};
}
const topicMatch = conversationId.match(/^(.+):topic:([^:]+)$/);
const topicMatch = conversationId.match(/^(.+):topic:([^:]+)$/i);
if (topicMatch) {
const [, chatId, topicId] = topicMatch;
return {
@@ -132,7 +132,7 @@ export function parseFeishuConversationId(params: {
};
}
const senderMatch = conversationId.match(/^(.+):sender:([^:]+)$/);
const senderMatch = conversationId.match(/^(.+):sender:([^:]+)$/i);
if (senderMatch) {
const [, chatId, senderOpenId] = senderMatch;
return {

View File

@@ -0,0 +1,42 @@
import { buildFeishuConversationId, parseFeishuConversationId } from "./conversation-id.js";
export function resolveFeishuParentConversationCandidates(rawId: string): string[] {
const parsed = parseFeishuConversationId({ conversationId: rawId });
if (!parsed) {
return [];
}
switch (parsed.scope) {
case "group_topic_sender":
return [
buildFeishuConversationId({
chatId: parsed.chatId,
scope: "group_topic",
topicId: parsed.topicId,
}),
parsed.chatId,
];
case "group_topic":
case "group_sender":
return [parsed.chatId];
case "group":
default:
return [];
}
}
export function resolveFeishuSessionConversation(params: {
kind: "group" | "channel";
rawId: string;
}) {
const parsed = parseFeishuConversationId({ conversationId: params.rawId });
if (!parsed) {
return null;
}
return {
id: parsed.canonicalConversationId,
baseConversationId: parsed.chatId,
parentConversationCandidates: resolveFeishuParentConversationCandidates(
parsed.canonicalConversationId,
),
};
}