feat(agent): maxSteps configurable, défaut 8->24 (tâches multi-outils) (v0.37.0)

Construire un workflow n8n (flux SDK) dépasse 8 étapes. maxAgentSteps via
CHLOVA_MAX_AGENT_STEPS, passé config -> ChatService -> runAgentTurn. 83 tests
verts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016w5jRe87MGdd6AMvXQcHNi
This commit is contained in:
Kantin-Petit
2026-06-24 00:11:45 +02:00
parent cb82b3165b
commit a29c9dbdf0
6 changed files with 31 additions and 3 deletions
+3
View File
@@ -20,6 +20,8 @@ export interface ChatServiceDeps {
systemPrompt: string;
logger: Logger;
store?: ConversationStore;
/** Plafond d'étapes par tour (multi-outils). Défaut runAgentTurn sinon. */
maxSteps?: number;
}
export interface ChatResult {
@@ -75,6 +77,7 @@ export class ChatService {
actor,
guard: this.deps.guard,
logger: this.deps.logger,
...(this.deps.maxSteps ? { maxSteps: this.deps.maxSteps } : {}),
});
this.deps.logger.info({ actor, steps }, "tour d'agent terminé");
return reply;
+1 -1
View File
@@ -46,7 +46,7 @@ export async function runAgentTurn(
input: AgentTurnInput,
): Promise<AgentTurnResult> {
const { client, tools, actor, guard, logger } = input;
const maxSteps = input.maxSteps ?? 8;
const maxSteps = input.maxSteps ?? 24;
const byName = new Map(tools.map((t) => [t.spec.name, t]));
const toolDefs = toOllamaTools(tools);
+12
View File
@@ -67,6 +67,17 @@ const schema = z.object({
// Backend
dbPath: z.string().default("./data/chlova.db"),
// Plafond d'étapes d'un tour d'agent (appels d'outils enchaînés). Les tâches
// multi-outils (ex. construire un workflow n8n via le SDK) en demandent
// beaucoup ; défaut généreux. Garde-fou anti-boucle conservé.
maxAgentSteps: z
.string()
.default("24")
.transform((v) => {
const n = Number.parseInt(v, 10);
return Number.isFinite(n) && n > 0 ? n : 24;
}),
// Alertes (Phase 3) : webhook n8n qui envoie le mail. Optionnel : si absent,
// les alertes sont seulement loggées (NullAlertSender). Peut contenir un token
// de chemin → traité comme secret (jamais loggé).
@@ -129,6 +140,7 @@ export function loadConfig(env: NodeJS.ProcessEnv = process.env): Config {
telegramBotToken: env.TELEGRAM_BOT_TOKEN,
telegramAllowedUserIds: env.TELEGRAM_ALLOWED_USER_IDS,
dbPath: env.CHLOVA_DB_PATH,
maxAgentSteps: env.CHLOVA_MAX_AGENT_STEPS,
alertWebhookUrl: env.ALERT_WEBHOOK_URL,
adminUser: env.CHLOVA_ADMIN_USER,
adminPasswordHash: env.CHLOVA_ADMIN_PASSWORD_HASH,
+1 -1
View File
@@ -113,7 +113,7 @@ async function main(): Promise<void> {
});
// Conversations persistées (mémoire multi-tour + reprise), même fichier SQLite.
const conversations = new ConversationStore(cfg.dbPath);
const chat = new ChatService({ client, tools, guard, systemPrompt, logger, store: conversations });
const chat = new ChatService({ client, tools, guard, systemPrompt, logger, store: conversations, maxSteps: cfg.maxAgentSteps });
// ── Surface Telegram (long-polling) — optionnelle ───────────────────────
// Démarrée seulement si un token est fourni. Sinon, surface API/UI seule