File size: 3,629 Bytes
76289e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
  buildChannelAccountBindings,
  listBoundAccountIds,
  resolveDefaultAgentBoundAccountId,
} from "./bindings.js";
import { resolveFirstBoundAccountId } from "./bound-account-read.js";

describe("route binding account helpers", () => {
  it.each([undefined, "", "  "])("includes implicit account %j in diagnostics", (accountId) => {
    const cfg: OpenClawConfig = {
      agents: { entries: { main: {} } },
      bindings: [{ agentId: "main", match: { channel: "telegram", accountId } }],
    };
    expect(listBoundAccountIds(cfg, "telegram")).toEqual(["default"]);
    expect(buildChannelAccountBindings(cfg)).toEqual(
      new Map([["telegram", new Map([["main", ["default"]]])]]),
    );
  });

  it.each([false, true])(
    "keeps implicit bindings out of outbound account selection (explicit sole: %s)",
    (explicitOwnership) => {
      const cfg: OpenClawConfig = {
        agents: { ...(explicitOwnership ? { ownership: "explicit" } : {}), entries: { main: {} } },
        channels: { telegram: { defaultAccount: "work" } },
        bindings: [{ agentId: "main", match: { channel: "telegram" } }],
      };
      expect(resolveDefaultAgentBoundAccountId(cfg, "telegram")).toBeNull();
      expect(
        resolveFirstBoundAccountId({ cfg, channelId: "telegram", agentId: "main" }),
      ).toBeUndefined();

      cfg.bindings = [
        { agentId: "main", match: { channel: "telegram" } },
        { agentId: "main", match: { channel: "telegram", accountId: "alerts" } },
      ];
      expect(resolveDefaultAgentBoundAccountId(cfg, "telegram")).toBe("alerts");
      expect(resolveFirstBoundAccountId({ cfg, channelId: "telegram", agentId: "main" })).toBe(
        "alerts",
      );
    },
  );

  it("preserves account order and agent scope while deduplicating implicit defaults", () => {
    const cfg: OpenClawConfig = {
      agents: { entries: { main: {}, support: {} } },
      bindings: [
        { agentId: "main", match: { channel: "telegram", accountId: "work" } },
        { agentId: "main", match: { channel: "telegram" } },
        { agentId: "main", match: { channel: "telegram", accountId: "default" } },
        {
          agentId: "support",
          match: { channel: "telegram", peer: { kind: "group", id: "group-a" } },
        },
        { agentId: "support", match: { channel: "telegram", accountId: "*" } },
        { agentId: "support", match: { channel: "slack", accountId: "alerts" } },
      ],
    };
    expect(listBoundAccountIds(cfg, "telegram")).toEqual(["default", "work"]);
    expect(buildChannelAccountBindings(cfg).get("telegram")).toEqual(
      new Map([
        ["main", ["work", "default"]],
        ["support", ["default"]],
      ]),
    );
    expect(resolveDefaultAgentBoundAccountId(cfg, "telegram")).toBeNull();
  });

  it.each([undefined, "explicit"] as const)(
    "uses the designated binding owner only with explicit ownership (%s)",
    (ownership) => {
      const cfg: OpenClawConfig = {
        agents: {
          ownership,
          defaults: { systemAgent: { agentId: "research" } },
          entries: { ops: { default: true }, research: {} },
        },
        bindings: [
          { agentId: "ops", match: { channel: "telegram", accountId: "legacy" } },
          { agentId: "research", match: { channel: "telegram", accountId: "designated" } },
        ],
      };
      expect(resolveDefaultAgentBoundAccountId(cfg, "telegram")).toBe(
        ownership === "explicit" ? "designated" : "legacy",
      );
    },
  );
});