executant 1.4.3 → 1.4.5
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/dist/index.js +73 -9
- package/dist/prompts/plan-judge.txt +2 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1295,17 +1295,81 @@ async function runPass3Judge(description, workflow2) {
|
|
|
1295
1295
|
function isNumericSequence(arr) {
|
|
1296
1296
|
return arr.every((item, i) => item === String(i + 1));
|
|
1297
1297
|
}
|
|
1298
|
+
function isLabeledSequence(arr) {
|
|
1299
|
+
if (arr.length < 2) return null;
|
|
1300
|
+
const m = arr[0].match(/^(.+\s)(\d+)$/);
|
|
1301
|
+
if (!m) return null;
|
|
1302
|
+
const prefix = m[1];
|
|
1303
|
+
return arr.every((item, i) => item === `${prefix}${i + 1}`) ? arr.length : null;
|
|
1304
|
+
}
|
|
1305
|
+
function parseSeqCommand(cmd) {
|
|
1306
|
+
const t = cmd.trim();
|
|
1307
|
+
const shorthand = t.match(/^seq\s+(\d+)$/);
|
|
1308
|
+
if (shorthand) return parseInt(shorthand[1], 10);
|
|
1309
|
+
const explicit = t.match(/^seq\s+1\s+(\d+)$/);
|
|
1310
|
+
if (explicit) return parseInt(explicit[1], 10);
|
|
1311
|
+
return null;
|
|
1312
|
+
}
|
|
1313
|
+
function extractCountFromName(name) {
|
|
1314
|
+
const m = name.match(/_of_(\d+)/);
|
|
1315
|
+
return m ? parseInt(m[1], 10) : null;
|
|
1316
|
+
}
|
|
1298
1317
|
function normalizeWorkflow(workflow2) {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1318
|
+
const steps = workflow2.steps.map((step) => {
|
|
1319
|
+
if (Array.isArray(step.forEach)) {
|
|
1320
|
+
const arr = step.forEach;
|
|
1321
|
+
const isNumeric = isNumericSequence(arr);
|
|
1322
|
+
const labeledN = !isNumeric ? isLabeledSequence(arr) : null;
|
|
1323
|
+
if (isNumeric || labeledN !== null) {
|
|
1303
1324
|
const { forEach, ...rest } = step;
|
|
1304
|
-
return { ...rest, repeat:
|
|
1325
|
+
return { ...rest, repeat: isNumeric ? arr.length : labeledN };
|
|
1305
1326
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1327
|
+
}
|
|
1328
|
+
if (typeof step.forEach === "string") {
|
|
1329
|
+
const n = parseSeqCommand(step.forEach);
|
|
1330
|
+
if (n !== null) {
|
|
1331
|
+
const { forEach, ...rest } = step;
|
|
1332
|
+
return { ...rest, repeat: n };
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
const prompt = typeof step.prompt === "string" ? step.prompt : "";
|
|
1336
|
+
if (prompt.includes("{{item}}") && step.forEach === void 0 && step.repeat === void 0) {
|
|
1337
|
+
const n = extractCountFromName(step.name);
|
|
1338
|
+
if (n !== null) return { ...step, repeat: n };
|
|
1339
|
+
}
|
|
1340
|
+
return step;
|
|
1341
|
+
});
|
|
1342
|
+
return { ...workflow2, steps: collapseSequentialSteps(steps) };
|
|
1343
|
+
}
|
|
1344
|
+
function collapseSequentialSteps(steps) {
|
|
1345
|
+
const result = [];
|
|
1346
|
+
let i = 0;
|
|
1347
|
+
while (i < steps.length) {
|
|
1348
|
+
const step = steps[i];
|
|
1349
|
+
if (step.forEach !== void 0 || step.repeat !== void 0) {
|
|
1350
|
+
result.push(step);
|
|
1351
|
+
i++;
|
|
1352
|
+
continue;
|
|
1353
|
+
}
|
|
1354
|
+
const m = step.name.match(/^(.+?)_1$/);
|
|
1355
|
+
if (!m) {
|
|
1356
|
+
result.push(step);
|
|
1357
|
+
i++;
|
|
1358
|
+
continue;
|
|
1359
|
+
}
|
|
1360
|
+
const prefix = m[1];
|
|
1361
|
+
let n = 1;
|
|
1362
|
+
while (i + n < steps.length && steps[i + n].name === `${prefix}_${n + 1}`) n++;
|
|
1363
|
+
if (n < 2) {
|
|
1364
|
+
result.push(step);
|
|
1365
|
+
i++;
|
|
1366
|
+
continue;
|
|
1367
|
+
}
|
|
1368
|
+
const { name, ...rest } = step;
|
|
1369
|
+
result.push({ ...rest, name: `${prefix}_{{item}}`, repeat: n });
|
|
1370
|
+
i += n;
|
|
1371
|
+
}
|
|
1372
|
+
return result;
|
|
1309
1373
|
}
|
|
1310
1374
|
async function* streamPlan(args) {
|
|
1311
1375
|
const { description, taskFile } = args;
|
|
@@ -1371,7 +1435,7 @@ async function* streamPlan(args) {
|
|
|
1371
1435
|
${basePrompt}` : basePrompt,
|
|
1372
1436
|
allowedTools: [],
|
|
1373
1437
|
permissionMode: "bypassPermissions",
|
|
1374
|
-
model: "opus",
|
|
1438
|
+
model: skipResearch ? "sonnet" : "opus",
|
|
1375
1439
|
appendSystemPrompt: PLAN_SYSTEM_RULES,
|
|
1376
1440
|
jsonSchema: WORKFLOW_JSON_SCHEMA
|
|
1377
1441
|
};
|
|
@@ -65,6 +65,8 @@ If the user's goal mentions "N times", "repeat N", "N iterations", or "N passes"
|
|
|
65
65
|
- Does any step use `forEach` with a sequential numeric array like `["1","2","3","4","5"]`?
|
|
66
66
|
- This is always wrong — `repeat: N` must be used instead of a numeric forEach array
|
|
67
67
|
- Reject and require the offending step be converted to `repeat: N`
|
|
68
|
+
- Does any single step's `prompt` describe doing something "N times" or "across N passes" inline, instead of using `repeat: N`? A step that says "do this 10 times" or "perform N passes" inside its prompt text rather than setting `repeat: N` is wrong — reject it and require it to be restructured as a single-pass prompt with `repeat: N` on the step
|
|
69
|
+
- Are there N consecutive steps with names like `step_1`, `step_2`, `step_3`? Sequential named steps are always wrong when they do the same thing — reject and require a single step with `repeat: N`
|
|
68
70
|
|
|
69
71
|
## Output Format
|
|
70
72
|
|