workflow-ai 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configs/pipeline.yaml +12 -5
- package/package.json +1 -1
- package/src/runner.mjs +11 -36
package/configs/pipeline.yaml
CHANGED
|
@@ -233,6 +233,12 @@ pipeline:
|
|
|
233
233
|
agent: qwen-code
|
|
234
234
|
fallback_agent: kilo-deepseek
|
|
235
235
|
skill: execute-task
|
|
236
|
+
counter: task_attempts
|
|
237
|
+
agent_by_attempt:
|
|
238
|
+
1: qwen-code
|
|
239
|
+
2: claude-sonnet
|
|
240
|
+
3: claude-opus
|
|
241
|
+
4: kilo-deepseek
|
|
236
242
|
goto:
|
|
237
243
|
default:
|
|
238
244
|
stage: move-to-review
|
|
@@ -275,6 +281,7 @@ pipeline:
|
|
|
275
281
|
agent: claude-sonnet
|
|
276
282
|
fallback_agent: qwen-code
|
|
277
283
|
skill: review-result
|
|
284
|
+
counter: task_attempts
|
|
278
285
|
goto:
|
|
279
286
|
passed:
|
|
280
287
|
stage: move-ticket
|
|
@@ -294,19 +301,19 @@ pipeline:
|
|
|
294
301
|
# -------------------------------------------------------------------------
|
|
295
302
|
# 4b. increment-task-attempts
|
|
296
303
|
# Отдельный стейдж обновления счётчика попыток выполнения тикета.
|
|
297
|
-
# При достижении max — блокирует тикет. Иначе —
|
|
304
|
+
# При достижении max — блокирует тикет. Иначе — отправляет на доработку.
|
|
305
|
+
# Проверка лимита происходит ДО повторного execute-task.
|
|
298
306
|
# -------------------------------------------------------------------------
|
|
299
307
|
increment-task-attempts:
|
|
300
308
|
description: "Обновить счётчик попыток выполнения тикета"
|
|
301
309
|
type: update-counter
|
|
302
310
|
counter: task_attempts
|
|
303
|
-
max:
|
|
311
|
+
max: 6
|
|
304
312
|
goto:
|
|
305
313
|
default:
|
|
306
|
-
stage:
|
|
314
|
+
stage: execute-task
|
|
307
315
|
params:
|
|
308
316
|
ticket_id: "$context.ticket_id"
|
|
309
|
-
target: ready
|
|
310
317
|
max_reached:
|
|
311
318
|
stage: move-ticket
|
|
312
319
|
params:
|
|
@@ -366,7 +373,7 @@ pipeline:
|
|
|
366
373
|
description: "Обновить счётчик итераций анализа плана"
|
|
367
374
|
type: update-counter
|
|
368
375
|
counter: plan_iterations
|
|
369
|
-
max:
|
|
376
|
+
max: 2
|
|
370
377
|
goto:
|
|
371
378
|
default:
|
|
372
379
|
stage: decompose-gaps
|
package/package.json
CHANGED
package/src/runner.mjs
CHANGED
|
@@ -681,7 +681,17 @@ class StageExecutor {
|
|
|
681
681
|
throw new Error(`Stage not found: ${stageId}`);
|
|
682
682
|
}
|
|
683
683
|
|
|
684
|
-
|
|
684
|
+
// Выбираем агента: если есть agent_by_attempt и счётчик — ротация по попыткам
|
|
685
|
+
let agentId = stage.agent;
|
|
686
|
+
if (stage.agent_by_attempt && stage.counter) {
|
|
687
|
+
const attempt = this.counters[stage.counter] || 0;
|
|
688
|
+
if (stage.agent_by_attempt[attempt]) {
|
|
689
|
+
agentId = stage.agent_by_attempt[attempt];
|
|
690
|
+
if (this.logger) {
|
|
691
|
+
this.logger.info(`Agent rotation: attempt ${attempt} → ${agentId}`, stageId);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
685
695
|
const agent = this.pipeline.agents[agentId];
|
|
686
696
|
if (!agent) {
|
|
687
697
|
throw new Error(`Agent not found: ${agentId}`);
|
|
@@ -1157,41 +1167,6 @@ class PipelineRunner {
|
|
|
1157
1167
|
this.updateContext(transition.params, result.result);
|
|
1158
1168
|
}
|
|
1159
1169
|
|
|
1160
|
-
// Проверяем retry-логику с agent_by_attempt
|
|
1161
|
-
if (transition.agent_by_attempt && stage.counter) {
|
|
1162
|
-
const attempt = this.counters[stage.counter] || 1;
|
|
1163
|
-
const maxAttempts = transition.max || 3;
|
|
1164
|
-
|
|
1165
|
-
if (attempt < maxAttempts) {
|
|
1166
|
-
// Ещё есть попытки — переходим на указанный stage с переопределением агента
|
|
1167
|
-
const nextStage = transition.stage || stageId;
|
|
1168
|
-
const overrideAgent = transition.agent_by_attempt[attempt];
|
|
1169
|
-
|
|
1170
|
-
if (overrideAgent) {
|
|
1171
|
-
// Переопределяем агента для следующей попытки
|
|
1172
|
-
stage.agent = overrideAgent;
|
|
1173
|
-
this.logger.info(`Retry attempt ${attempt}: overriding agent to ${overrideAgent}`, stageId);
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
this.logger.retry(stageId, attempt, maxAttempts);
|
|
1177
|
-
this.logger.gotoTransition(stageId, nextStage, status, transition.params);
|
|
1178
|
-
return nextStage;
|
|
1179
|
-
} else {
|
|
1180
|
-
// Попытки исчерпаны — переходим на on_max
|
|
1181
|
-
this.logger.info(`Max attempts (${maxAttempts}) reached for ${stageId}`, stageId);
|
|
1182
|
-
this.logger.retry(stageId, attempt, maxAttempts);
|
|
1183
|
-
|
|
1184
|
-
if (transition.on_max) {
|
|
1185
|
-
if (transition.on_max.params) {
|
|
1186
|
-
this.updateContext(transition.on_max.params, result.result);
|
|
1187
|
-
}
|
|
1188
|
-
const nextStage = transition.on_max.stage || 'end';
|
|
1189
|
-
this.logger.gotoTransition(stageId, nextStage, status, transition.on_max.params);
|
|
1190
|
-
return nextStage;
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
1170
|
const nextStage = transition.stage || 'end';
|
|
1196
1171
|
this.logger.gotoTransition(stageId, nextStage, status, transition.params);
|
|
1197
1172
|
return nextStage;
|