feat(policy-file): move channel overrides to standalone channelPoliciesFile with hot reload

This commit is contained in:
2026-02-26 00:28:34 +00:00
parent d6f908b813
commit 682d9a336e
8 changed files with 79 additions and 39 deletions

View File

@@ -4,15 +4,7 @@ export type WhisperGateConfig = {
listMode?: "human-list" | "agent-list";
humanList?: string[];
agentList?: string[];
channelPolicies?: Record<
string,
{
listMode?: "human-list" | "agent-list";
humanList?: string[];
agentList?: string[];
endSymbols?: string[];
}
>;
channelPoliciesFile?: string;
// backward compatibility
bypassUserIds?: string[];
endSymbols?: string[];
@@ -20,6 +12,13 @@ export type WhisperGateConfig = {
noReplyModel: string;
};
export type ChannelPolicy = {
listMode?: "human-list" | "agent-list";
humanList?: string[];
agentList?: string[];
endSymbols?: string[];
};
export type Decision = {
shouldUseNoReply: boolean;
reason: string;
@@ -30,7 +29,7 @@ function getLastChar(input: string): string {
return t.length ? t[t.length - 1] : "";
}
function resolvePolicy(config: WhisperGateConfig, channelId?: string) {
function resolvePolicy(config: WhisperGateConfig, channelId?: string, channelPolicies?: Record<string, ChannelPolicy>) {
const globalMode = config.listMode || "human-list";
const globalHuman = config.humanList || config.bypassUserIds || [];
const globalAgent = config.agentList || [];
@@ -40,7 +39,7 @@ function resolvePolicy(config: WhisperGateConfig, channelId?: string) {
return { listMode: globalMode, humanList: globalHuman, agentList: globalAgent, endSymbols: globalEnd };
}
const cp = config.channelPolicies || {};
const cp = channelPolicies || {};
const scoped = cp[channelId];
if (!scoped) {
return { listMode: globalMode, humanList: globalHuman, agentList: globalAgent, endSymbols: globalEnd };
@@ -58,6 +57,7 @@ export function evaluateDecision(params: {
config: WhisperGateConfig;
channel?: string;
channelId?: string;
channelPolicies?: Record<string, ChannelPolicy>;
senderId?: string;
content?: string;
}): Decision {
@@ -72,7 +72,7 @@ export function evaluateDecision(params: {
return { shouldUseNoReply: false, reason: "non_discord" };
}
const policy = resolvePolicy(config, params.channelId);
const policy = resolvePolicy(config, params.channelId, params.channelPolicies);
const mode = policy.listMode;
const humanList = policy.humanList;