feat(browser): 增加 sequence 组合块能力

新增单层 sequence 容器以组合现有 orchestration blocks,并补充 sequence 内失败定位能力。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
walker1211andClaude Opus 4.7 committed 2026-04-20 18:55:24 +08:00
1 parent 26baa019e3
commit 0038b063ac
2 files changed
+374

No files matched your search

+39
View File
@@ -2438,6 +2438,9 @@ function formatOrchestrationSummary(session) {
`error: ${session.error || 'none'}`,
`status: ${session.status}`,
];
if (session.failedSequenceStepIndex !== null && session.failedSequenceStepIndex !== undefined) {
lines.push(`failedSequenceStepIndex: ${session.failedSequenceStepIndex}`);
}
if (session.errorDetails?.failedAssertionIndex !== undefined) {
lines.push(`failedAssertionIndex: ${session.errorDetails.failedAssertionIndex}`);
lines.push(`field: ${session.errorDetails.field}`);
@@ -2523,6 +2526,7 @@ const SUPPORTED_ORCHESTRATION_BLOCK_TYPES = new Set([
'wait_for_then_press_key',
'run_replay_sequence',
'assert_query',
'sequence',
]);
const SUPPORTED_ASSERTION_OPERATORS = new Set(['equals', 'contains', 'gt', 'gte', 'lt', 'lte']);
@@ -2669,6 +2673,21 @@ function validateOrchestrationBlock(block) {
}
}
function requireSequenceSteps(block) {
const steps = Array.isArray(block.args?.steps) ? block.args.steps : null;
if (!steps || steps.length === 0) {
throw new Error('sequence steps must be a non-empty array');
}
return steps;
}
function validateSequenceStep(step) {
validateOrchestrationBlock(step);
if (step.type === 'sequence') {
throw new Error('sequence does not support nested sequence blocks');
}
}
function normalizeRecordedEvent(pageId, event) {
if (!event || typeof event !== 'object') {
return null;
@@ -5116,9 +5135,28 @@ async function executeOrchestrationBlock(session, block) {
return;
}
if (block.type === 'sequence') {
await executeSequenceSteps(session, block);
return;
}
throw new Error('unsupported orchestration block type');
}
async function executeSequenceSteps(session, block) {
const steps = requireSequenceSteps(block);
for (let index = 0; index < steps.length; index += 1) {
const step = steps[index];
validateSequenceStep(step);
try {
await executeOrchestrationBlock(session, step);
} catch (error) {
session.failedSequenceStepIndex = index;
throw error;
}
}
}
async function executeOrchestrationBlocks(session) {
for (let index = 0; index < session.blocks.length; index += 1) {
const block = session.blocks[index];
@@ -5154,6 +5192,7 @@ async function handleStartOrchestration(toolArgs) {
completedBlocks: 0,
currentBlockIndex: 0,
failedBlockIndex: null,
failedSequenceStepIndex: null,
error: null,
blocks,
};