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:
+4
-1
@@ -47,7 +47,10 @@ CHLOVA_LOG_LEVEL=info
|
|||||||
# Gate de phase : 1 = lecture seule (défaut, fail-safe) ; 2 = écriture sous
|
# Gate de phase : 1 = lecture seule (défaut, fail-safe) ; 2 = écriture sous
|
||||||
# gatekeeper + cycle need-review. Toute valeur autre que "2" retombe sur 1.
|
# gatekeeper + cycle need-review. Toute valeur autre que "2" retombe sur 1.
|
||||||
CHLOVA_PHASE=1
|
CHLOVA_PHASE=1
|
||||||
CHLOVA_DB_PATH=./data/chlova.db # SQLite : table assets (need-review, Phase 2)
|
CHLOVA_DB_PATH=./data/chlova.db # SQLite : assets (need-review) + conversations
|
||||||
|
# Plafond d'étapes par tour d'agent (appels d'outils enchaînés). Les tâches
|
||||||
|
# multi-outils (construire un workflow n8n) en demandent beaucoup. Défaut 24.
|
||||||
|
CHLOVA_MAX_AGENT_STEPS=24
|
||||||
# Alertes (Phase 3) : URL du webhook n8n qui envoie le mail (workflow
|
# Alertes (Phase 3) : URL du webhook n8n qui envoie le mail (workflow
|
||||||
# workflows-n8n/chlova-alerts.v1.0.0.json). Vide = alertes log-only (fail-safe).
|
# workflows-n8n/chlova-alerts.v1.0.0.json). Vide = alertes log-only (fail-safe).
|
||||||
# Peut contenir un token de chemin → secret, jamais commité.
|
# Peut contenir un token de chemin → secret, jamais commité.
|
||||||
|
|||||||
@@ -6,6 +6,16 @@ incompatibles. Chaque ligne renvoie à un commit dédié (un artefact = un commi
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.37.0] — 2026-06-24 — maxSteps configurable (tâches multi-outils)
|
||||||
|
### Changed
|
||||||
|
- Plafond d'étapes d'un tour d'agent : défaut **8 → 24**, configurable via
|
||||||
|
`CHLOVA_MAX_AGENT_STEPS` (`config.maxAgentSteps` → `ChatService` →
|
||||||
|
`runAgentTurn`). Construire un workflow n8n (SDK : sdk_reference, search_nodes,
|
||||||
|
get_node_types, validate, create…) dépassait 8 étapes et coupait avant la fin.
|
||||||
|
### Notes
|
||||||
|
- Vérifié en Phase 2 live : le gatekeeper a correctement BLOQUÉ
|
||||||
|
`n8n.create_workflow_from_code` (review requise) — comportement attendu.
|
||||||
|
|
||||||
## [0.36.2] — 2026-06-23 — fix hauteur layout chat (sidebar + barre de saisie)
|
## [0.36.2] — 2026-06-23 — fix hauteur layout chat (sidebar + barre de saisie)
|
||||||
### Fixed
|
### Fixed
|
||||||
- Shell en **`h-dvh`** (hauteur définie) au lieu de `min-h-dvh` : `h-full` des
|
- Shell en **`h-dvh`** (hauteur définie) au lieu de `min-h-dvh` : `h-full` des
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ export interface ChatServiceDeps {
|
|||||||
systemPrompt: string;
|
systemPrompt: string;
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
store?: ConversationStore;
|
store?: ConversationStore;
|
||||||
|
/** Plafond d'étapes par tour (multi-outils). Défaut runAgentTurn sinon. */
|
||||||
|
maxSteps?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChatResult {
|
export interface ChatResult {
|
||||||
@@ -75,6 +77,7 @@ export class ChatService {
|
|||||||
actor,
|
actor,
|
||||||
guard: this.deps.guard,
|
guard: this.deps.guard,
|
||||||
logger: this.deps.logger,
|
logger: this.deps.logger,
|
||||||
|
...(this.deps.maxSteps ? { maxSteps: this.deps.maxSteps } : {}),
|
||||||
});
|
});
|
||||||
this.deps.logger.info({ actor, steps }, "tour d'agent terminé");
|
this.deps.logger.info({ actor, steps }, "tour d'agent terminé");
|
||||||
return reply;
|
return reply;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export async function runAgentTurn(
|
|||||||
input: AgentTurnInput,
|
input: AgentTurnInput,
|
||||||
): Promise<AgentTurnResult> {
|
): Promise<AgentTurnResult> {
|
||||||
const { client, tools, actor, guard, logger } = input;
|
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 byName = new Map(tools.map((t) => [t.spec.name, t]));
|
||||||
const toolDefs = toOllamaTools(tools);
|
const toolDefs = toOllamaTools(tools);
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,17 @@ const schema = z.object({
|
|||||||
// Backend
|
// Backend
|
||||||
dbPath: z.string().default("./data/chlova.db"),
|
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,
|
// Alertes (Phase 3) : webhook n8n qui envoie le mail. Optionnel : si absent,
|
||||||
// les alertes sont seulement loggées (NullAlertSender). Peut contenir un token
|
// les alertes sont seulement loggées (NullAlertSender). Peut contenir un token
|
||||||
// de chemin → traité comme secret (jamais loggé).
|
// 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,
|
telegramBotToken: env.TELEGRAM_BOT_TOKEN,
|
||||||
telegramAllowedUserIds: env.TELEGRAM_ALLOWED_USER_IDS,
|
telegramAllowedUserIds: env.TELEGRAM_ALLOWED_USER_IDS,
|
||||||
dbPath: env.CHLOVA_DB_PATH,
|
dbPath: env.CHLOVA_DB_PATH,
|
||||||
|
maxAgentSteps: env.CHLOVA_MAX_AGENT_STEPS,
|
||||||
alertWebhookUrl: env.ALERT_WEBHOOK_URL,
|
alertWebhookUrl: env.ALERT_WEBHOOK_URL,
|
||||||
adminUser: env.CHLOVA_ADMIN_USER,
|
adminUser: env.CHLOVA_ADMIN_USER,
|
||||||
adminPasswordHash: env.CHLOVA_ADMIN_PASSWORD_HASH,
|
adminPasswordHash: env.CHLOVA_ADMIN_PASSWORD_HASH,
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ async function main(): Promise<void> {
|
|||||||
});
|
});
|
||||||
// Conversations persistées (mémoire multi-tour + reprise), même fichier SQLite.
|
// Conversations persistées (mémoire multi-tour + reprise), même fichier SQLite.
|
||||||
const conversations = new ConversationStore(cfg.dbPath);
|
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 ───────────────────────
|
// ── Surface Telegram (long-polling) — optionnelle ───────────────────────
|
||||||
// Démarrée seulement si un token est fourni. Sinon, surface API/UI seule
|
// Démarrée seulement si un token est fourni. Sinon, surface API/UI seule
|
||||||
|
|||||||
Reference in New Issue
Block a user