Files
flynn/src/agents/router.ts
T

62 lines
1.6 KiB
TypeScript

/**
* AgentRouter resolves which agent config to use for a given channel+sender.
*
* Resolution order (first match wins):
* 1. Exact sender match (channel:senderId)
* 2. Glob pattern sender match
* 3. Channel match
* 4. default_agent fallback
*/
import type { RoutingConfig } from '../config/schema.js';
export type { RoutingConfig };
/**
* Convert a simple glob pattern to a RegExp.
* Supports `*` (match any sequence of characters).
* All other regex-special characters are escaped.
*/
function patternToRegex(pattern: string): RegExp {
const escaped = pattern
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
.replace(/\*/g, '.*');
return new RegExp(`^${escaped}$`);
}
export class AgentRouter {
private config: RoutingConfig;
constructor(config: RoutingConfig) {
this.config = config;
}
/**
* Resolve the agent config name for a channel + sender pair.
* Returns undefined if no match and no default is configured.
*/
resolve(channel: string, senderId: string): string | undefined {
const senderKey = `${channel}:${senderId}`;
// 1. Exact sender match
if (this.config.senders[senderKey]) {
return this.config.senders[senderKey];
}
// 2. Glob pattern sender match
for (const [pattern, agentName] of Object.entries(this.config.senders)) {
if (pattern.includes('*') && patternToRegex(pattern).test(senderKey)) {
return agentName;
}
}
// 3. Channel match
if (this.config.channels[channel]) {
return this.config.channels[channel];
}
// 4. Default fallback
return this.config.default_agent;
}
}