feat: wire multi-agent config and routing

Co-authored-by: Mark Pors <1078320+pors@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-01-09 12:44:23 +00:00
parent 81beda0772
commit 7b81d97ec2
189 changed files with 4340 additions and 2903 deletions

View File

@@ -360,7 +360,7 @@ describe("createTelegramBot", () => {
loadConfig.mockReturnValue({
identity: { name: "Bert" },
routing: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
telegram: { groups: { "*": { requireMention: true } } },
});
@@ -438,8 +438,11 @@ describe("createTelegramBot", () => {
replySpy.mockReset();
loadConfig.mockReturnValue({
messages: { ackReaction: "👀", ackReactionScope: "group-mentions" },
routing: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
messages: {
ackReaction: "👀",
ackReactionScope: "group-mentions",
groupChat: { mentionPatterns: ["\\bbert\\b"] },
},
telegram: { groups: { "*": { requireMention: true } } },
});
@@ -483,7 +486,7 @@ describe("createTelegramBot", () => {
replySpy.mockReset();
loadConfig.mockReturnValue({
routing: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
telegram: { groups: { "*": { requireMention: true } } },
});
@@ -515,7 +518,7 @@ describe("createTelegramBot", () => {
replySpy.mockReset();
loadConfig.mockReturnValue({
routing: { groupChat: { mentionPatterns: [] } },
messages: { groupChat: { mentionPatterns: [] } },
telegram: { groups: { "*": { requireMention: true } } },
});
@@ -790,17 +793,15 @@ describe("createTelegramBot", () => {
);
loadConfig.mockReturnValue({
telegram: { groups: { "*": { requireMention: true } } },
routing: {
bindings: [
{
agentId: "ops",
match: {
provider: "telegram",
peer: { kind: "group", id: "123" },
},
bindings: [
{
agentId: "ops",
match: {
provider: "telegram",
peer: { kind: "group", id: "123" },
},
],
},
},
],
session: { store: storePath },
});

View File

@@ -5,6 +5,8 @@ import { sequentialize } from "@grammyjs/runner";
import { apiThrottler } from "@grammyjs/transformer-throttler";
import type { ApiClientOptions, Message } from "grammy";
import { Bot, InputFile, webhookCallback } from "grammy";
import { resolveDefaultAgentId } from "../agents/agent-scope.js";
import { resolveAckReaction } from "../agents/identity.js";
import { EmbeddedBlockChunker } from "../agents/pi-embedded-block-chunker.js";
import {
chunkMarkdownText,
@@ -225,7 +227,6 @@ export function createTelegramBot(opts: TelegramBotOptions) {
const nativeEnabled = cfg.commands?.native === true;
const nativeDisabledExplicit = cfg.commands?.native === false;
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
const ackReaction = (cfg.messages?.ackReaction ?? "").trim();
const ackReactionScope = cfg.messages?.ackReactionScope ?? "group-mentions";
const mediaMaxBytes =
(opts.mediaMaxMb ?? telegramCfg.mediaMaxMb ?? 5) * 1024 * 1024;
@@ -260,7 +261,7 @@ export function createTelegramBot(opts: TelegramBotOptions) {
messageThreadId?: number;
sessionKey?: string;
}) => {
const agentId = params.agentId ?? cfg.agent?.id ?? "main";
const agentId = params.agentId ?? resolveDefaultAgentId(cfg);
const sessionKey =
params.sessionKey ??
`agent:${agentId}:telegram:group:${buildTelegramGroupPeerId(params.chatId, params.messageThreadId)}`;
@@ -500,6 +501,7 @@ export function createTelegramBot(opts: TelegramBotOptions) {
}
// ACK reactions
const ackReaction = resolveAckReaction(cfg, route.agentId);
const shouldAckReaction = () => {
if (!ackReaction) return false;
if (ackReactionScope === "all") return true;

View File

@@ -30,7 +30,7 @@ const { initSpy, runSpy, loadConfig } = vi.hoisted(() => ({
stop: vi.fn(),
})),
loadConfig: vi.fn(() => ({
agent: { maxConcurrent: 2 },
agents: { defaults: { maxConcurrent: 2 } },
telegram: {},
})),
}));
@@ -79,7 +79,7 @@ vi.mock("../auto-reply/reply.js", () => ({
describe("monitorTelegramProvider (grammY)", () => {
beforeEach(() => {
loadConfig.mockReturnValue({
agent: { maxConcurrent: 2 },
agents: { defaults: { maxConcurrent: 2 } },
telegram: {},
});
initSpy.mockClear();
@@ -109,7 +109,7 @@ describe("monitorTelegramProvider (grammY)", () => {
it("uses agent maxConcurrent for runner concurrency", async () => {
runSpy.mockClear();
loadConfig.mockReturnValue({
agent: { maxConcurrent: 3 },
agents: { defaults: { maxConcurrent: 3 } },
telegram: {},
});

View File

@@ -28,7 +28,7 @@ export function createTelegramRunnerOptions(
): RunOptions<unknown> {
return {
sink: {
concurrency: cfg.agent?.maxConcurrent ?? 1,
concurrency: cfg.agents?.defaults?.maxConcurrent ?? 1,
},
runner: {
fetch: {