refactor: unify peer kind to ChatType, rename dm to direct (#11881)

* fix: use .js extension for ESM imports of RoutePeerKind

The imports incorrectly used .ts extension which doesn't resolve
with moduleResolution: NodeNext. Changed to .js and added 'type'
import modifier.

* fix tsconfig

* refactor: unify peer kind to ChatType, rename dm to direct

- Replace RoutePeerKind with ChatType throughout codebase
- Change 'dm' literal values to 'direct' in routing/session keys
- Keep backward compat: normalizeChatType accepts 'dm' -> 'direct'
- Add ChatType export to plugin-sdk, deprecate RoutePeerKind
- Update session key parsing to accept both 'dm' and 'direct' markers
- Update all channel monitors and extensions to use ChatType

BREAKING CHANGE: Session keys now use 'direct' instead of 'dm'.
Existing 'dm' keys still work via backward compat layer.

* fix tests

* test: update session key expectations for dmdirect migration

- Fix test expectations to expect :direct: in generated output
- Add explicit backward compat test for normalizeChatType('dm')
- Keep input test data with :dm: keys to verify backward compat

* fix: accept legacy 'dm' in session key parsing for backward compat

getDmHistoryLimitFromSessionKey now accepts both :dm: and :direct:
to ensure old session keys continue to work correctly.

* test: add explicit backward compat tests for dmdirect migration

- session-key.test.ts: verify both :dm: and :direct: keys are valid
- getDmHistoryLimitFromSessionKey: verify both formats work

* feat: backward compat for resetByType.dm config key

* test: skip unix-path Nix tests on Windows
This commit is contained in:
max
2026-02-08 16:20:52 -08:00
committed by GitHub
parent 0b07e15b63
commit 223eee0a20
64 changed files with 377 additions and 185 deletions

View File

@@ -228,4 +228,18 @@ describe("getDmHistoryLimitFromSessionKey", () => {
} as OpenClawConfig;
expect(getDmHistoryLimitFromSessionKey("telegram:dm:123", config)).toBe(5);
});
describe("backward compatibility", () => {
it("accepts both legacy :dm: and new :direct: session keys", () => {
const config = {
channels: { telegram: { dmHistoryLimit: 10 } },
} as OpenClawConfig;
// Legacy format with :dm:
expect(getDmHistoryLimitFromSessionKey("telegram:dm:123", config)).toBe(10);
expect(getDmHistoryLimitFromSessionKey("agent:main:telegram:dm:123", config)).toBe(10);
// New format with :direct:
expect(getDmHistoryLimitFromSessionKey("telegram:direct:123", config)).toBe(10);
expect(getDmHistoryLimitFromSessionKey("agent:main:telegram:direct:123", config)).toBe(10);
});
});
});

View File

@@ -58,7 +58,8 @@ export function getDmHistoryLimitFromSessionKey(
const kind = providerParts[1]?.toLowerCase();
const userIdRaw = providerParts.slice(2).join(":");
const userId = stripThreadSuffix(userIdRaw);
if (kind !== "dm") {
// Accept both "direct" (new) and "dm" (legacy) for backward compat
if (kind !== "direct" && kind !== "dm") {
return undefined;
}

View File

@@ -190,15 +190,16 @@ function inferDeliveryFromSessionKey(agentSessionKey?: string): CronDelivery | n
}
// buildAgentPeerSessionKey encodes peers as:
// - dm:<peerId>
// - <channel>:dm:<peerId>
// - <channel>:<accountId>:dm:<peerId>
// - direct:<peerId>
// - <channel>:direct:<peerId>
// - <channel>:<accountId>:direct:<peerId>
// - <channel>:group:<peerId>
// - <channel>:channel:<peerId>
// Note: legacy keys may use "dm" instead of "direct".
// Threaded sessions append :thread:<id>, which we strip so delivery targets the parent peer.
// NOTE: Telegram forum topics encode as <chatId>:topic:<topicId> and should be preserved.
const markerIndex = parts.findIndex(
(part) => part === "dm" || part === "group" || part === "channel",
(part) => part === "direct" || part === "dm" || part === "group" || part === "channel",
);
if (markerIndex === -1) {
return null;