fix(channels): add optional defaultAccount routing

This commit is contained in:
Peter Steinberger
2026-03-02 04:03:13 +00:00
parent 0437ac1a89
commit 41537e9303
45 changed files with 461 additions and 35 deletions

View File

@@ -100,6 +100,39 @@ describe("LINE accounts", () => {
});
describe("resolveDefaultLineAccountId", () => {
it("prefers channels.line.defaultAccount when configured", () => {
const cfg: OpenClawConfig = {
channels: {
line: {
defaultAccount: "business",
accounts: {
business: { enabled: true },
support: { enabled: true },
},
},
},
};
const id = resolveDefaultLineAccountId(cfg);
expect(id).toBe("business");
});
it("normalizes channels.line.defaultAccount before lookup", () => {
const cfg: OpenClawConfig = {
channels: {
line: {
defaultAccount: "Business Ops",
accounts: {
"business-ops": { enabled: true },
},
},
},
};
const id = resolveDefaultLineAccountId(cfg);
expect(id).toBe("business-ops");
});
it("returns first named account when default not configured", () => {
const cfg: OpenClawConfig = {
channels: {
@@ -115,6 +148,22 @@ describe("LINE accounts", () => {
expect(id).toBe("business");
});
it("falls back when channels.line.defaultAccount is missing", () => {
const cfg: OpenClawConfig = {
channels: {
line: {
defaultAccount: "missing",
accounts: {
business: { enabled: true },
},
},
},
};
const id = resolveDefaultLineAccountId(cfg);
expect(id).toBe("business");
});
});
describe("normalizeAccountId", () => {

View File

@@ -3,6 +3,7 @@ import type { OpenClawConfig } from "../config/config.js";
import {
DEFAULT_ACCOUNT_ID,
normalizeAccountId as normalizeSharedAccountId,
normalizeOptionalAccountId,
} from "../routing/account-id.js";
import { resolveAccountEntry } from "../routing/account-lookup.js";
import type {
@@ -124,8 +125,16 @@ export function resolveLineAccount(params: {
accountConfig,
});
const {
accounts: _ignoredAccounts,
defaultAccount: _ignoredDefaultAccount,
...lineBase
} = (lineConfig ?? {}) as LineConfig & {
accounts?: unknown;
defaultAccount?: unknown;
};
const mergedConfig: LineConfig & LineAccountConfig = {
...lineConfig,
...lineBase,
...accountConfig,
};
@@ -172,6 +181,15 @@ export function listLineAccountIds(cfg: OpenClawConfig): string[] {
}
export function resolveDefaultLineAccountId(cfg: OpenClawConfig): string {
const preferred = normalizeOptionalAccountId(
(cfg.channels?.line as LineConfig | undefined)?.defaultAccount,
);
if (
preferred &&
listLineAccountIds(cfg).some((accountId) => normalizeSharedAccountId(accountId) === preferred)
) {
return preferred;
}
const ids = listLineAccountIds(cfg);
if (ids.includes(DEFAULT_ACCOUNT_ID)) {
return DEFAULT_ACCOUNT_ID;

View File

@@ -35,6 +35,7 @@ const LineAccountConfigSchema = LineCommonConfigSchema.extend({
export const LineConfigSchema = LineCommonConfigSchema.extend({
accounts: z.record(z.string(), LineAccountConfigSchema.optional()).optional(),
defaultAccount: z.string().optional(),
groups: z.record(z.string(), LineGroupConfigSchema.optional()).optional(),
}).strict();

View File

@@ -32,6 +32,8 @@ interface LineAccountBaseConfig {
export interface LineConfig extends LineAccountBaseConfig {
/** Per-account overrides keyed by account id. */
accounts?: Record<string, LineAccountConfig>;
/** Optional default account id when multiple accounts are configured. */
defaultAccount?: string;
}
export interface LineAccountConfig extends LineAccountBaseConfig {}