edsger 0.34.0 → 0.35.0
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/api/features/approval-checker.js +6 -8
- package/dist/commands/agent-workflow/chat-worker.js +2 -1
- package/dist/commands/agent-workflow/processor.js +3 -1
- package/dist/commands/code-review/index.js +5 -7
- package/dist/commands/workflow/phase-orchestrator.js +16 -32
- package/dist/constants.js +2 -0
- package/dist/index.js +3 -1
- package/dist/phases/app-store-generation/__tests__/agent.test.js +1 -3
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +2 -4
- package/dist/phases/app-store-generation/agent.js +1 -3
- package/dist/phases/app-store-generation/index.js +4 -3
- package/dist/phases/app-store-generation/screenshot-composer.js +3 -5
- package/dist/phases/autonomous/index.js +4 -3
- package/dist/phases/branch-planning/context.js +7 -7
- package/dist/phases/branch-planning/index.js +5 -3
- package/dist/phases/bug-fixing/analyzer.js +13 -13
- package/dist/phases/bug-fixing/context-fetcher.js +9 -9
- package/dist/phases/bug-fixing/mcp-server.js +14 -17
- package/dist/phases/code-implementation/context.js +5 -5
- package/dist/phases/code-implementation/index.js +5 -4
- package/dist/phases/code-implementation-verification/agent.js +3 -1
- package/dist/phases/code-refine/context.js +1 -1
- package/dist/phases/code-refine/index.js +4 -6
- package/dist/phases/code-refine/refine-iteration.js +10 -10
- package/dist/phases/code-refine-verification/index.js +80 -82
- package/dist/phases/code-review/index.js +8 -8
- package/dist/phases/code-testing/analyzer.js +3 -1
- package/dist/phases/code-testing/context-fetcher.js +5 -5
- package/dist/phases/feature-analysis/agent.js +1 -3
- package/dist/phases/feature-analysis/context.js +5 -5
- package/dist/phases/feature-analysis/index.js +4 -4
- package/dist/phases/feature-analysis/outcome.d.ts +1 -1
- package/dist/phases/feature-analysis/outcome.js +7 -7
- package/dist/phases/feature-analysis-verification/index.js +6 -6
- package/dist/phases/functional-testing/analyzer.js +4 -2
- package/dist/phases/functional-testing/context-fetcher.js +5 -5
- package/dist/phases/functional-testing/http-fallback.js +4 -2
- package/dist/phases/functional-testing/mcp-server.js +3 -3
- package/dist/phases/growth-analysis/agent.js +1 -3
- package/dist/phases/pr-execution/index.js +3 -1
- package/dist/phases/pr-splitting/context.js +6 -6
- package/dist/phases/pr-splitting/index.js +3 -1
- package/dist/phases/pull-request/handler.js +2 -4
- package/dist/phases/task/agent.js +6 -8
- package/dist/phases/technical-design/context.js +5 -5
- package/dist/phases/technical-design/index.js +9 -8
- package/dist/phases/test-cases-analysis/agent.js +1 -3
- package/dist/phases/test-cases-analysis/context.js +5 -5
- package/dist/phases/test-cases-analysis/index.js +3 -3
- package/dist/phases/test-cases-analysis/outcome.d.ts +1 -1
- package/dist/phases/test-cases-analysis/outcome.js +4 -4
- package/dist/phases/user-stories-analysis/agent.js +1 -3
- package/dist/phases/user-stories-analysis/context.js +5 -5
- package/dist/phases/user-stories-analysis/index.js +3 -3
- package/dist/phases/user-stories-analysis/outcome.d.ts +1 -1
- package/dist/phases/user-stories-analysis/outcome.js +4 -4
- package/dist/services/coaching/coaching-loop.js +1 -1
- package/dist/services/coaching/self-rating.js +1 -1
- package/dist/services/phase-ratings.js +2 -1
- package/dist/services/video/__tests__/video-pipeline.test.js +3 -1
- package/dist/services/video/retry.js +5 -2
- package/dist/services/video/screenshot-generator.js +1 -1
- package/dist/services/video/video-assembler.d.ts +1 -1
- package/dist/services/video/video-assembler.js +3 -3
- package/dist/utils/conflict-resolver.js +13 -15
- package/dist/utils/git-branch-manager-async.js +5 -7
- package/dist/utils/git-push.js +2 -2
- package/package.json +1 -1
|
@@ -59,14 +59,12 @@ export async function executeTask(taskPrompt, systemPrompt, config, verbose) {
|
|
|
59
59
|
summary: message.result || lastAssistantResponse || 'Task completed',
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
69
|
-
}
|
|
62
|
+
logError(`Task incomplete: ${message.subtype}`);
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
summary: lastAssistantResponse ||
|
|
66
|
+
`Task ended with status: ${message.subtype}`,
|
|
67
|
+
};
|
|
70
68
|
}
|
|
71
69
|
}
|
|
72
70
|
return {
|
|
@@ -10,7 +10,7 @@ export async function fetchTechnicalDesignContext(featureId, verbose) {
|
|
|
10
10
|
logInfo(`Fetching complete technical design context for feature: ${featureId}`);
|
|
11
11
|
}
|
|
12
12
|
// Fetch all required data in parallel for better performance
|
|
13
|
-
const [feature,
|
|
13
|
+
const [feature, userStories, testCases] = await Promise.all([
|
|
14
14
|
getFeature(featureId, verbose),
|
|
15
15
|
getUserStories(featureId, verbose),
|
|
16
16
|
getTestCases(featureId, verbose),
|
|
@@ -20,15 +20,15 @@ export async function fetchTechnicalDesignContext(featureId, verbose) {
|
|
|
20
20
|
logInfo(`✅ Technical design context fetched successfully:`);
|
|
21
21
|
logInfo(` Feature: ${feature.name}`);
|
|
22
22
|
logInfo(` Product: ${product.name}`);
|
|
23
|
-
logInfo(` User Stories: ${
|
|
24
|
-
logInfo(` Test Cases: ${
|
|
23
|
+
logInfo(` User Stories: ${userStories.length}`);
|
|
24
|
+
logInfo(` Test Cases: ${testCases.length} (${testCases.filter((tc) => tc.is_critical).length} critical)`);
|
|
25
25
|
logInfo(` Existing Technical Design: ${feature.technical_design ? 'Yes' : 'No'}`);
|
|
26
26
|
}
|
|
27
27
|
return {
|
|
28
28
|
feature,
|
|
29
29
|
product,
|
|
30
|
-
user_stories,
|
|
31
|
-
test_cases,
|
|
30
|
+
user_stories: userStories,
|
|
31
|
+
test_cases: testCases,
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
catch (error) {
|
|
@@ -20,7 +20,9 @@ function userMessage(content) {
|
|
|
20
20
|
}
|
|
21
21
|
async function* prompt(analysisPrompt) {
|
|
22
22
|
yield userMessage(analysisPrompt);
|
|
23
|
-
await new Promise((res) =>
|
|
23
|
+
await new Promise((res) => {
|
|
24
|
+
setTimeout(res, 10000);
|
|
25
|
+
});
|
|
24
26
|
}
|
|
25
27
|
export const generateTechnicalDesign = async (options, config, checklistContext
|
|
26
28
|
// eslint-disable-next-line complexity -- orchestration function with context assembly, design generation, and verification
|
|
@@ -111,6 +113,7 @@ export const generateTechnicalDesign = async (options, config, checklistContext
|
|
|
111
113
|
const parsed = JSON.parse(jsonStr);
|
|
112
114
|
const design = parsed.technical_design_result?.technical_design;
|
|
113
115
|
if (design && typeof design === 'string') {
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
114
117
|
structuredDesignResult.technical_design = design;
|
|
115
118
|
await updateTechnicalDesign(featureId, design, verbose);
|
|
116
119
|
}
|
|
@@ -138,7 +141,7 @@ export const generateTechnicalDesign = async (options, config, checklistContext
|
|
|
138
141
|
maxIterations,
|
|
139
142
|
verbose,
|
|
140
143
|
});
|
|
141
|
-
verificationResult = verificationCycle
|
|
144
|
+
({ verificationResult } = verificationCycle);
|
|
142
145
|
// If verification passed, exit
|
|
143
146
|
if (verificationCycle.passed) {
|
|
144
147
|
if (verbose) {
|
|
@@ -267,10 +270,8 @@ async function prepareDesignContext(featureId, checklistContext, verbose) {
|
|
|
267
270
|
logInfo(`📄 Feedbacks section length: ${feedbacksInfo.length} characters`);
|
|
268
271
|
}
|
|
269
272
|
}
|
|
270
|
-
else {
|
|
271
|
-
|
|
272
|
-
logInfo('ℹ️ No unresolved feedbacks found for this phase');
|
|
273
|
-
}
|
|
273
|
+
else if (verbose) {
|
|
274
|
+
logInfo('ℹ️ No unresolved feedbacks found for this phase');
|
|
274
275
|
}
|
|
275
276
|
}
|
|
276
277
|
catch (error) {
|
|
@@ -325,9 +326,9 @@ async function prepareDesignContext(featureId, checklistContext, verbose) {
|
|
|
325
326
|
* Strip the "Your Previous Technical Design" section from the improvement prompt.
|
|
326
327
|
* When resuming a session, the agent already has the design in its history.
|
|
327
328
|
*/
|
|
328
|
-
function stripPreviousDesignSection(
|
|
329
|
+
function stripPreviousDesignSection(systemPrompt) {
|
|
329
330
|
// Remove content between deterministic markers (added in prompts.ts)
|
|
330
|
-
return
|
|
331
|
+
return systemPrompt.replace(/<!-- PREVIOUS_DESIGN_START -->[\s\S]*?<!-- PREVIOUS_DESIGN_END -->/, '');
|
|
331
332
|
}
|
|
332
333
|
/**
|
|
333
334
|
* Execute design query and parse result
|
|
@@ -15,9 +15,7 @@ export function parseAnalysisResult(responseText) {
|
|
|
15
15
|
if (jsonResult && jsonResult.analysis) {
|
|
16
16
|
return { analysis: jsonResult.analysis };
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
return { error: 'Invalid JSON structure' };
|
|
20
|
-
}
|
|
18
|
+
return { error: 'Invalid JSON structure' };
|
|
21
19
|
}
|
|
22
20
|
catch (error) {
|
|
23
21
|
return {
|
|
@@ -10,7 +10,7 @@ export async function fetchTestCasesAnalysisContext(featureId, verbose) {
|
|
|
10
10
|
if (verbose) {
|
|
11
11
|
logInfo(`Fetching test cases analysis context for feature: ${featureId}`);
|
|
12
12
|
}
|
|
13
|
-
const [feature,
|
|
13
|
+
const [feature, existingUserStories, existingTestCases] = await Promise.all([
|
|
14
14
|
getFeature(featureId, verbose),
|
|
15
15
|
getUserStories(featureId, verbose),
|
|
16
16
|
getTestCases(featureId, verbose),
|
|
@@ -20,14 +20,14 @@ export async function fetchTestCasesAnalysisContext(featureId, verbose) {
|
|
|
20
20
|
logInfo(`✅ Test cases analysis context fetched successfully:`);
|
|
21
21
|
logInfo(` Feature: ${feature.name}`);
|
|
22
22
|
logInfo(` Product: ${product.name}`);
|
|
23
|
-
logInfo(` User Stories: ${
|
|
24
|
-
logInfo(` Existing Test Cases: ${
|
|
23
|
+
logInfo(` User Stories: ${existingUserStories.length}`);
|
|
24
|
+
logInfo(` Existing Test Cases: ${existingTestCases.length}`);
|
|
25
25
|
}
|
|
26
26
|
return {
|
|
27
27
|
feature,
|
|
28
28
|
product,
|
|
29
|
-
existing_user_stories,
|
|
30
|
-
existing_test_cases,
|
|
29
|
+
existing_user_stories: existingUserStories,
|
|
30
|
+
existing_test_cases: existingTestCases,
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
@@ -89,8 +89,8 @@ export const analyseTestCases = async (options, config, checklistContext
|
|
|
89
89
|
const parsed = parseAnalysisResult(responseText);
|
|
90
90
|
if (parsed.analysis) {
|
|
91
91
|
await deleteTestCaseArtifacts(currentDraftTestCaseIds, verbose);
|
|
92
|
-
const { testCaseIds } = await saveTestCasesAsDraft(featureId, parsed.analysis.created_test_cases || [], verbose);
|
|
93
|
-
currentDraftTestCaseIds =
|
|
92
|
+
const { testCaseIds: newTestCaseIds } = await saveTestCasesAsDraft(featureId, parsed.analysis.created_test_cases || [], verbose);
|
|
93
|
+
currentDraftTestCaseIds = newTestCaseIds;
|
|
94
94
|
structuredAnalysisResult = parsed.analysis;
|
|
95
95
|
}
|
|
96
96
|
else {
|
|
@@ -113,7 +113,7 @@ export const analyseTestCases = async (options, config, checklistContext
|
|
|
113
113
|
featureId,
|
|
114
114
|
verbose,
|
|
115
115
|
});
|
|
116
|
-
verificationResult = verificationCycle
|
|
116
|
+
({ verificationResult } = verificationCycle);
|
|
117
117
|
if (verificationCycle.passed) {
|
|
118
118
|
if (verbose) {
|
|
119
119
|
logInfo('✅ Verification passed! Updating all draft test cases to pending_approval status...');
|
|
@@ -4,7 +4,7 @@ export declare function getAllDraftTestCaseIds(featureId: string, verbose?: bool
|
|
|
4
4
|
export declare function deleteTestCaseArtifacts(testCaseIds: string[], verbose?: boolean): Promise<void>;
|
|
5
5
|
export declare function deleteSpecificTestCases(featureId: string, deletedTestCaseIds: string[], deletionReasons: Record<string, string>, verbose?: boolean): Promise<void>;
|
|
6
6
|
export declare function updateTestCasesToReady(testCaseIds: string[], verbose?: boolean): Promise<void>;
|
|
7
|
-
export declare function saveTestCasesAsDraft(featureId: string,
|
|
7
|
+
export declare function saveTestCasesAsDraft(featureId: string, createdTestCases: any[], verbose?: boolean): Promise<{
|
|
8
8
|
testCaseIds: string[];
|
|
9
9
|
}>;
|
|
10
10
|
export interface TestCasesAnalysisResult {
|
|
@@ -77,16 +77,16 @@ export async function updateTestCasesToReady(testCaseIds, verbose) {
|
|
|
77
77
|
}
|
|
78
78
|
export async function saveTestCasesAsDraft(featureId,
|
|
79
79
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
|
-
|
|
80
|
+
createdTestCases, verbose) {
|
|
81
81
|
const testCaseIds = [];
|
|
82
|
-
if (
|
|
82
|
+
if (createdTestCases && createdTestCases.length > 0) {
|
|
83
83
|
if (verbose) {
|
|
84
|
-
logInfo(`Saving ${
|
|
84
|
+
logInfo(`Saving ${createdTestCases.length} test cases as draft...`);
|
|
85
85
|
}
|
|
86
86
|
try {
|
|
87
87
|
const result = (await callMcpEndpoint('test_cases/create', {
|
|
88
88
|
feature_id: featureId,
|
|
89
|
-
test_cases:
|
|
89
|
+
test_cases: createdTestCases.map((testCase) => ({
|
|
90
90
|
name: testCase.name,
|
|
91
91
|
description: testCase.description,
|
|
92
92
|
is_critical: testCase.is_critical || false,
|
|
@@ -15,9 +15,7 @@ export function parseAnalysisResult(responseText) {
|
|
|
15
15
|
if (jsonResult && jsonResult.analysis) {
|
|
16
16
|
return { analysis: jsonResult.analysis };
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
return { error: 'Invalid JSON structure' };
|
|
20
|
-
}
|
|
18
|
+
return { error: 'Invalid JSON structure' };
|
|
21
19
|
}
|
|
22
20
|
catch (error) {
|
|
23
21
|
return {
|
|
@@ -10,7 +10,7 @@ export async function fetchUserStoriesAnalysisContext(featureId, verbose) {
|
|
|
10
10
|
if (verbose) {
|
|
11
11
|
logInfo(`Fetching user stories analysis context for feature: ${featureId}`);
|
|
12
12
|
}
|
|
13
|
-
const [feature,
|
|
13
|
+
const [feature, existingUserStories, existingTestCases] = await Promise.all([
|
|
14
14
|
getFeature(featureId, verbose),
|
|
15
15
|
getUserStories(featureId, verbose),
|
|
16
16
|
getTestCases(featureId, verbose),
|
|
@@ -20,14 +20,14 @@ export async function fetchUserStoriesAnalysisContext(featureId, verbose) {
|
|
|
20
20
|
logInfo(`✅ User stories analysis context fetched successfully:`);
|
|
21
21
|
logInfo(` Feature: ${feature.name}`);
|
|
22
22
|
logInfo(` Product: ${product.name}`);
|
|
23
|
-
logInfo(` Existing User Stories: ${
|
|
24
|
-
logInfo(` Existing Test Cases: ${
|
|
23
|
+
logInfo(` Existing User Stories: ${existingUserStories.length}`);
|
|
24
|
+
logInfo(` Existing Test Cases: ${existingTestCases.length}`);
|
|
25
25
|
}
|
|
26
26
|
return {
|
|
27
27
|
feature,
|
|
28
28
|
product,
|
|
29
|
-
existing_user_stories,
|
|
30
|
-
existing_test_cases,
|
|
29
|
+
existing_user_stories: existingUserStories,
|
|
30
|
+
existing_test_cases: existingTestCases,
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
@@ -89,8 +89,8 @@ export const analyseUserStories = async (options, config, checklistContext
|
|
|
89
89
|
const parsed = parseAnalysisResult(responseText);
|
|
90
90
|
if (parsed.analysis) {
|
|
91
91
|
await deleteUserStoryArtifacts(currentDraftUserStoryIds, verbose);
|
|
92
|
-
const { userStoryIds } = await saveUserStoriesAsDraft(featureId, parsed.analysis.created_user_stories || [], verbose);
|
|
93
|
-
currentDraftUserStoryIds =
|
|
92
|
+
const { userStoryIds: newUserStoryIds } = await saveUserStoriesAsDraft(featureId, parsed.analysis.created_user_stories || [], verbose);
|
|
93
|
+
currentDraftUserStoryIds = newUserStoryIds;
|
|
94
94
|
structuredAnalysisResult = parsed.analysis;
|
|
95
95
|
}
|
|
96
96
|
else {
|
|
@@ -113,7 +113,7 @@ export const analyseUserStories = async (options, config, checklistContext
|
|
|
113
113
|
featureId,
|
|
114
114
|
verbose,
|
|
115
115
|
});
|
|
116
|
-
verificationResult = verificationCycle
|
|
116
|
+
({ verificationResult } = verificationCycle);
|
|
117
117
|
if (verificationCycle.passed) {
|
|
118
118
|
if (verbose) {
|
|
119
119
|
logInfo('✅ Verification passed! Updating all draft user stories to pending_approval status...');
|
|
@@ -4,7 +4,7 @@ export declare function getAllDraftUserStoryIds(featureId: string, verbose?: boo
|
|
|
4
4
|
export declare function deleteUserStoryArtifacts(userStoryIds: string[], verbose?: boolean): Promise<void>;
|
|
5
5
|
export declare function deleteSpecificUserStories(featureId: string, deletedUserStoryIds: string[], deletionReasons: Record<string, string>, verbose?: boolean): Promise<void>;
|
|
6
6
|
export declare function updateUserStoriesToReady(userStoryIds: string[], verbose?: boolean): Promise<void>;
|
|
7
|
-
export declare function saveUserStoriesAsDraft(featureId: string,
|
|
7
|
+
export declare function saveUserStoriesAsDraft(featureId: string, createdUserStories: any[], verbose?: boolean): Promise<{
|
|
8
8
|
userStoryIds: string[];
|
|
9
9
|
}>;
|
|
10
10
|
export interface UserStoriesAnalysisResult {
|
|
@@ -77,16 +77,16 @@ export async function updateUserStoriesToReady(userStoryIds, verbose) {
|
|
|
77
77
|
}
|
|
78
78
|
export async function saveUserStoriesAsDraft(featureId,
|
|
79
79
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
|
-
|
|
80
|
+
createdUserStories, verbose) {
|
|
81
81
|
const userStoryIds = [];
|
|
82
|
-
if (
|
|
82
|
+
if (createdUserStories && createdUserStories.length > 0) {
|
|
83
83
|
if (verbose) {
|
|
84
|
-
logInfo(`Saving ${
|
|
84
|
+
logInfo(`Saving ${createdUserStories.length} user stories as draft...`);
|
|
85
85
|
}
|
|
86
86
|
try {
|
|
87
87
|
const result = (await callMcpEndpoint('user_stories/create', {
|
|
88
88
|
feature_id: featureId,
|
|
89
|
-
user_stories:
|
|
89
|
+
user_stories: createdUserStories.map((story) => ({
|
|
90
90
|
title: story.title,
|
|
91
91
|
description: story.description,
|
|
92
92
|
status: 'draft',
|
|
@@ -71,7 +71,7 @@ export function isStagnant(ratings) {
|
|
|
71
71
|
// eslint-disable-next-line complexity -- coaching loop with rating, decision, and improvement cycles
|
|
72
72
|
export async function runCoachingLoop(options) {
|
|
73
73
|
const { featureId, phase, onImproved, checklistItems, verbose } = options;
|
|
74
|
-
let executionSessionId = options
|
|
74
|
+
let { executionSessionId } = options;
|
|
75
75
|
let coachingSessionId = null;
|
|
76
76
|
const allRatings = [];
|
|
77
77
|
let iteration = 0;
|
|
@@ -117,7 +117,7 @@ export function parseSelfRating(response, phase, verbose) {
|
|
|
117
117
|
const rating = parsed.self_rating || parsed;
|
|
118
118
|
// Validate score
|
|
119
119
|
const score = Number(rating.score);
|
|
120
|
-
if (isNaN(score) || score < 0 || score > 100) {
|
|
120
|
+
if (Number.isNaN(score) || score < 0 || score > 100) {
|
|
121
121
|
throw new Error(`Invalid score: ${rating.score}`);
|
|
122
122
|
}
|
|
123
123
|
// Build criteria_scores with defaults for missing criteria
|
|
@@ -60,7 +60,8 @@ export async function getPhaseRatings(featureId, phase, verbose) {
|
|
|
60
60
|
feature_id: featureId,
|
|
61
61
|
phase,
|
|
62
62
|
});
|
|
63
|
-
const ratings = (result?.ratings ||
|
|
63
|
+
const ratings = (result?.ratings ||
|
|
64
|
+
[]);
|
|
64
65
|
if (verbose) {
|
|
65
66
|
logDebug(`Fetched ${ratings.length} ratings for ${phase} (feature: ${featureId})`, verbose);
|
|
66
67
|
}
|
|
@@ -233,7 +233,9 @@ void describe('Concurrency Limiter', () => {
|
|
|
233
233
|
if (currentConcurrent > maxConcurrent) {
|
|
234
234
|
maxConcurrent = currentConcurrent;
|
|
235
235
|
}
|
|
236
|
-
await new Promise((r) =>
|
|
236
|
+
await new Promise((r) => {
|
|
237
|
+
setTimeout(r, 10);
|
|
238
|
+
});
|
|
237
239
|
currentConcurrent--;
|
|
238
240
|
return i;
|
|
239
241
|
});
|
|
@@ -31,7 +31,8 @@ export async function fetchWithRetry(url, init, options = {}) {
|
|
|
31
31
|
}
|
|
32
32
|
catch (error) {
|
|
33
33
|
// Network errors (ECONNRESET, ETIMEDOUT, etc.) are retryable
|
|
34
|
-
if (error instanceof TypeError ||
|
|
34
|
+
if (error instanceof TypeError ||
|
|
35
|
+
(error instanceof Error && isNetworkError(error))) {
|
|
35
36
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
36
37
|
if (attempt < maxRetries) {
|
|
37
38
|
const delay = calculateBackoff(attempt, baseDelayMs);
|
|
@@ -69,5 +70,7 @@ function isNetworkError(error) {
|
|
|
69
70
|
message.includes('abort'));
|
|
70
71
|
}
|
|
71
72
|
function sleep(ms) {
|
|
72
|
-
return new Promise((resolve) =>
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
setTimeout(resolve, ms);
|
|
75
|
+
});
|
|
73
76
|
}
|
|
@@ -14,7 +14,7 @@ import { generateDeviceFrameHtml, } from './device-frames.js';
|
|
|
14
14
|
*/
|
|
15
15
|
async function loadChromium() {
|
|
16
16
|
try {
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-new-func -- dynamic import to avoid bundler resolution of optional peer dependency
|
|
18
18
|
const pw = await Function('return import("playwright")')();
|
|
19
19
|
return pw.chromium;
|
|
20
20
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Uses ffmpeg for professional-quality video output.
|
|
4
4
|
*/
|
|
5
5
|
import type { CapturedScene } from './screenshot-generator.js';
|
|
6
|
-
import type
|
|
6
|
+
import { type GeneratedAudio } from './tts-generator.js';
|
|
7
7
|
export interface VideoAssemblyOptions {
|
|
8
8
|
/** Output file path for the final video */
|
|
9
9
|
outputPath: string;
|
|
@@ -162,8 +162,8 @@ export async function assembleVideo(scenes, audioFiles, options, verbose) {
|
|
|
162
162
|
if (!optWidth || !optHeight) {
|
|
163
163
|
const detected = detectScreenshotResolution(scenes[0]?.screenshotPath);
|
|
164
164
|
if (detected) {
|
|
165
|
-
|
|
166
|
-
height = detected
|
|
165
|
+
;
|
|
166
|
+
({ width, height } = detected);
|
|
167
167
|
if (verbose) {
|
|
168
168
|
logInfo(`Auto-detected video resolution: ${width}x${height}`);
|
|
169
169
|
}
|
|
@@ -179,7 +179,7 @@ export async function assembleVideo(scenes, audioFiles, options, verbose) {
|
|
|
179
179
|
const sceneDurations = [];
|
|
180
180
|
for (const scene of sortedScenes) {
|
|
181
181
|
const audio = audioMap.get(scene.order);
|
|
182
|
-
let duration = scene
|
|
182
|
+
let { duration } = scene;
|
|
183
183
|
if (audio) {
|
|
184
184
|
try {
|
|
185
185
|
duration = await getAudioDuration(audio.audioPath);
|
|
@@ -167,23 +167,21 @@ export async function resolveConflictsWithAgent(config = {}) {
|
|
|
167
167
|
failedFiles: [],
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
logError(` Last message: ${lastMessage.substring(0, 200)}...`);
|
|
177
|
-
}
|
|
170
|
+
// Rebase still in progress - something went wrong
|
|
171
|
+
const remainingConflicts = getConflictFiles();
|
|
172
|
+
if (verbose) {
|
|
173
|
+
logError(`❌ Rebase still in progress with ${remainingConflicts.length} conflicts`);
|
|
174
|
+
if (lastMessage) {
|
|
175
|
+
logError(` Last message: ${lastMessage.substring(0, 200)}...`);
|
|
178
176
|
}
|
|
179
|
-
abortRebase(verbose);
|
|
180
|
-
return {
|
|
181
|
-
success: false,
|
|
182
|
-
resolvedFiles: [],
|
|
183
|
-
failedFiles: remainingConflicts,
|
|
184
|
-
error: `Rebase not completed. Remaining conflicts: ${remainingConflicts.join(', ')}`,
|
|
185
|
-
};
|
|
186
177
|
}
|
|
178
|
+
abortRebase(verbose);
|
|
179
|
+
return {
|
|
180
|
+
success: false,
|
|
181
|
+
resolvedFiles: [],
|
|
182
|
+
failedFiles: remainingConflicts,
|
|
183
|
+
error: `Rebase not completed. Remaining conflicts: ${remainingConflicts.join(', ')}`,
|
|
184
|
+
};
|
|
187
185
|
}
|
|
188
186
|
catch (error) {
|
|
189
187
|
if (verbose) {
|
|
@@ -337,13 +337,11 @@ export async function switchToFeatureBranchAndRebaseAsync(options) {
|
|
|
337
337
|
resolvedFiles: result.resolvedFiles,
|
|
338
338
|
};
|
|
339
339
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
`Please resolve conflicts manually and try again.`);
|
|
346
|
-
}
|
|
340
|
+
// Conflict resolution failed, abort rebase
|
|
341
|
+
abortRebase(verbose);
|
|
342
|
+
throw new Error(`Failed to automatically resolve conflicts during rebase ${featureBranch} with ${actualRebaseTarget}.\n` +
|
|
343
|
+
`${result.error || 'Unknown error'}\n` +
|
|
344
|
+
`Please resolve conflicts manually and try again.`);
|
|
347
345
|
}
|
|
348
346
|
// No conflict resolution attempted or not a conflict error
|
|
349
347
|
// Abort rebase and throw error
|
package/dist/utils/git-push.js
CHANGED
|
@@ -39,7 +39,7 @@ export function gitPush(options) {
|
|
|
39
39
|
const credArgs = buildCredentialArgs(token);
|
|
40
40
|
const execOpts = {
|
|
41
41
|
cwd,
|
|
42
|
-
stdio:
|
|
42
|
+
stdio: verbose ? 'inherit' : 'pipe',
|
|
43
43
|
};
|
|
44
44
|
if (verbose) {
|
|
45
45
|
logInfo(`📤 Pushing branch ${branchName} to remote...`);
|
|
@@ -87,7 +87,7 @@ export function gitForcePush(options) {
|
|
|
87
87
|
const credArgs = buildCredentialArgs(token);
|
|
88
88
|
const execOpts = {
|
|
89
89
|
cwd,
|
|
90
|
-
stdio:
|
|
90
|
+
stdio: verbose ? 'inherit' : 'pipe',
|
|
91
91
|
};
|
|
92
92
|
if (verbose) {
|
|
93
93
|
logInfo(`📤 Force pushing ${branchName} to remote...`);
|