mirror of https://github.com/openclaw/openclaw.git
docs: clarify session conversation base routing
This commit is contained in:
parent
efa8632360
commit
d3ee04de63
|
|
@ -154,7 +154,7 @@
|
|||
"exportName": "ChannelMessageActionAdapter",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 553,
|
||||
"line": 556,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -163,7 +163,7 @@
|
|||
"exportName": "ChannelMessageActionContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 517,
|
||||
"line": 520,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1170,7 +1170,7 @@
|
|||
"exportName": "BaseProbeResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 596,
|
||||
"line": 599,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1179,7 +1179,7 @@
|
|||
"exportName": "BaseTokenResolution",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 602,
|
||||
"line": 605,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1224,7 +1224,7 @@
|
|||
"exportName": "ChannelMessageActionAdapter",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 553,
|
||||
"line": 556,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1233,7 +1233,7 @@
|
|||
"exportName": "ChannelMessageActionContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 517,
|
||||
"line": 520,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1752,7 +1752,7 @@
|
|||
"exportName": "BaseProbeResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 596,
|
||||
"line": 599,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1761,7 +1761,7 @@
|
|||
"exportName": "BaseTokenResolution",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 602,
|
||||
"line": 605,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1797,7 +1797,7 @@
|
|||
"exportName": "ChannelAgentPromptAdapter",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 490,
|
||||
"line": 493,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1977,7 +1977,7 @@
|
|||
"exportName": "ChannelDirectoryEntry",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 504,
|
||||
"line": 507,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -1986,7 +1986,7 @@
|
|||
"exportName": "ChannelDirectoryEntryKind",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 502,
|
||||
"line": 505,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -2130,7 +2130,7 @@
|
|||
"exportName": "ChannelMessageActionAdapter",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 553,
|
||||
"line": 556,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -2139,7 +2139,7 @@
|
|||
"exportName": "ChannelMessageActionContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 517,
|
||||
"line": 520,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -2274,7 +2274,7 @@
|
|||
"exportName": "ChannelPollContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 584,
|
||||
"line": 587,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -2283,7 +2283,7 @@
|
|||
"exportName": "ChannelPollResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 575,
|
||||
"line": 578,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -2427,7 +2427,7 @@
|
|||
"exportName": "ChannelToolSend",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 546,
|
||||
"line": 549,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
@ -3738,7 +3738,7 @@
|
|||
"exportName": "ChannelMessageActionContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 517,
|
||||
"line": 520,
|
||||
"path": "src/channels/plugins/types.core.ts"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -38,7 +38,9 @@ generic `:thread:` bookkeeping, and dispatch.
|
|||
If your platform stores extra scope inside conversation ids, keep that parsing
|
||||
in the plugin with `messaging.resolveSessionConversation(...)`. That is the
|
||||
canonical hook for mapping `rawId` to the base conversation id, optional thread
|
||||
id, and any `parentConversationCandidates`.
|
||||
id, explicit `baseConversationId`, and any `parentConversationCandidates`.
|
||||
When you return `parentConversationCandidates`, keep them ordered from the
|
||||
narrowest parent to the broadest/base conversation.
|
||||
|
||||
Bundled plugins that need the same parsing before the channel registry boots
|
||||
can also expose a top-level `session-key-api.ts` file with a matching
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ describe("feishuPlugin messaging", () => {
|
|||
}),
|
||||
).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(
|
||||
|
|
@ -206,6 +207,7 @@ describe("feishuPlugin messaging", () => {
|
|||
}),
|
||||
).toEqual({
|
||||
id: "oc_group_chat:topic:om_topic_root",
|
||||
baseConversationId: "oc_group_chat",
|
||||
parentConversationCandidates: ["oc_group_chat"],
|
||||
});
|
||||
expect(
|
||||
|
|
@ -215,6 +217,7 @@ describe("feishuPlugin messaging", () => {
|
|||
}),
|
||||
).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"],
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export function resolveFeishuSessionConversation(params: {
|
|||
}
|
||||
return {
|
||||
id: parsed.canonicalConversationId,
|
||||
baseConversationId: parsed.chatId,
|
||||
parentConversationCandidates: resolveFeishuParentConversationCandidates(
|
||||
parsed.canonicalConversationId,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ describe("telegramPlugin messaging", () => {
|
|||
).toEqual({
|
||||
id: "-1001",
|
||||
threadId: "77",
|
||||
baseConversationId: "-1001",
|
||||
parentConversationCandidates: ["-1001"],
|
||||
});
|
||||
expect(
|
||||
|
|
@ -207,6 +208,7 @@ describe("telegramPlugin messaging", () => {
|
|||
).toEqual({
|
||||
id: "-1001",
|
||||
threadId: "77",
|
||||
baseConversationId: "-1001",
|
||||
parentConversationCandidates: ["-1001"],
|
||||
});
|
||||
expect(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export function resolveTelegramSessionConversation(params: {
|
|||
return {
|
||||
id: parsed.chatId,
|
||||
threadId: parsed.topicId,
|
||||
baseConversationId: parsed.chatId,
|
||||
parentConversationCandidates: [parsed.chatId],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,7 @@ function resolveGroupContextFromSessionKey(sessionKey?: string | null): {
|
|||
}
|
||||
const resolvedConversation = resolveSessionConversationRef(raw);
|
||||
if (resolvedConversation) {
|
||||
const groupId =
|
||||
resolvedConversation.parentConversationCandidates.at(-1) ?? resolvedConversation.id;
|
||||
const groupId = resolvedConversation.baseConversationId;
|
||||
if (!groupId) {
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ describe("session conversation routing", () => {
|
|||
id: "general",
|
||||
threadId: "1699999999.0001",
|
||||
baseSessionKey: "agent:main:slack:channel:general",
|
||||
baseConversationId: "general",
|
||||
parentConversationCandidates: ["general"],
|
||||
});
|
||||
});
|
||||
|
|
@ -36,6 +37,7 @@ describe("session conversation routing", () => {
|
|||
id: "-100123",
|
||||
threadId: "77",
|
||||
baseSessionKey: "agent:main:telegram:group:-100123",
|
||||
baseConversationId: "-100123",
|
||||
parentConversationCandidates: ["-100123"],
|
||||
});
|
||||
expect(resolveSessionThreadInfo("agent:main:telegram:group:-100123:topic:77")).toEqual({
|
||||
|
|
@ -57,6 +59,7 @@ describe("session conversation routing", () => {
|
|||
id: "-100123",
|
||||
threadId: "77",
|
||||
baseSessionKey: "agent:main:telegram:group:-100123",
|
||||
baseConversationId: "-100123",
|
||||
parentConversationCandidates: ["-100123"],
|
||||
});
|
||||
});
|
||||
|
|
@ -76,6 +79,7 @@ describe("session conversation routing", () => {
|
|||
threadId: undefined,
|
||||
baseSessionKey:
|
||||
"agent:main:feishu:group: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"],
|
||||
});
|
||||
});
|
||||
|
|
@ -93,6 +97,7 @@ describe("session conversation routing", () => {
|
|||
threadId: undefined,
|
||||
baseSessionKey:
|
||||
"agent:main:feishu:group: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(
|
||||
|
|
@ -140,6 +145,7 @@ describe("session conversation routing", () => {
|
|||
).toEqual({
|
||||
id: "room:sender:user",
|
||||
threadId: undefined,
|
||||
baseConversationId: "room",
|
||||
parentConversationCandidates: ["room"],
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { getChannelPlugin, normalizeChannelId as normalizeAnyChannelId } from ".
|
|||
export type ResolvedSessionConversation = {
|
||||
id: string;
|
||||
threadId: string | undefined;
|
||||
baseConversationId: string;
|
||||
parentConversationCandidates: string[];
|
||||
};
|
||||
|
||||
|
|
@ -24,12 +25,14 @@ export type ResolvedSessionConversationRef = {
|
|||
id: string;
|
||||
threadId: string | undefined;
|
||||
baseSessionKey: string;
|
||||
baseConversationId: string;
|
||||
parentConversationCandidates: string[];
|
||||
};
|
||||
|
||||
type SessionConversationHookResult = {
|
||||
id: string;
|
||||
threadId?: string | null;
|
||||
baseConversationId?: string | null;
|
||||
parentConversationCandidates?: string[];
|
||||
};
|
||||
|
||||
|
|
@ -100,6 +103,7 @@ function buildGenericConversationResolution(rawId: string): ResolvedSessionConve
|
|||
return {
|
||||
id,
|
||||
threadId: parsed.threadId,
|
||||
baseConversationId: id,
|
||||
parentConversationCandidates: dedupeConversationIds(
|
||||
parsed.threadId ? [parsed.baseSessionKey] : [],
|
||||
),
|
||||
|
|
@ -116,6 +120,10 @@ function normalizeSessionConversationResolution(
|
|||
return {
|
||||
id: resolved.id.trim(),
|
||||
threadId: resolved.threadId?.trim() || undefined,
|
||||
baseConversationId:
|
||||
resolved.baseConversationId?.trim() ||
|
||||
dedupeConversationIds(resolved.parentConversationCandidates ?? []).at(-1) ||
|
||||
resolved.id.trim(),
|
||||
parentConversationCandidates: dedupeConversationIds(
|
||||
resolved.parentConversationCandidates ?? [],
|
||||
),
|
||||
|
|
@ -197,9 +205,12 @@ function resolveSessionConversationResolution(params: {
|
|||
rawId,
|
||||
}) ?? resolved.parentConversationCandidates),
|
||||
);
|
||||
const baseConversationId =
|
||||
parentConversationCandidates.at(-1) ?? resolved.baseConversationId ?? resolved.id;
|
||||
|
||||
return {
|
||||
...resolved,
|
||||
baseConversationId,
|
||||
parentConversationCandidates,
|
||||
};
|
||||
}
|
||||
|
|
@ -236,6 +247,7 @@ export function resolveSessionConversationRef(
|
|||
id: resolved.id,
|
||||
threadId: resolved.threadId,
|
||||
baseSessionKey: buildBaseSessionKey(raw, resolved.id),
|
||||
baseConversationId: resolved.baseConversationId,
|
||||
parentConversationCandidates: resolved.parentConversationCandidates,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -401,14 +401,17 @@ export type ChannelMessagingAdapter = {
|
|||
* Canonical plugin-owned session conversation grammar.
|
||||
* Use this when the provider encodes thread or scoped-conversation semantics
|
||||
* inside `rawId` (for example Telegram topics or Feishu sender scopes).
|
||||
* Return `parentConversationCandidates` here when you can so parsing and
|
||||
* inheritance stay in one place.
|
||||
* Return `baseConversationId` and `parentConversationCandidates` here when
|
||||
* you can so parsing and inheritance stay in one place.
|
||||
* `parentConversationCandidates`, when present, should be ordered from the
|
||||
* narrowest parent to the broadest/base conversation.
|
||||
* Bundled plugins that need the same grammar before runtime bootstrap can
|
||||
* mirror this contract through a top-level `session-key-api.ts` surface.
|
||||
*/
|
||||
resolveSessionConversation?: (params: { kind: "group" | "channel"; rawId: string }) => {
|
||||
id: string;
|
||||
threadId?: string | null;
|
||||
baseConversationId?: string | null;
|
||||
parentConversationCandidates?: string[];
|
||||
} | null;
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue