popeye-cli 1.4.7 → 1.5.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/README.md +222 -63
- package/dist/adapters/gemini.d.ts +1 -0
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +9 -4
- package/dist/adapters/gemini.js.map +1 -1
- package/dist/adapters/grok.d.ts +1 -0
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +9 -4
- package/dist/adapters/grok.js.map +1 -1
- package/dist/adapters/openai.d.ts +1 -1
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +35 -9
- package/dist/adapters/openai.js.map +1 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +42 -0
- package/dist/cli/interactive.js.map +1 -1
- package/dist/generators/all.d.ts +4 -1
- package/dist/generators/all.d.ts.map +1 -1
- package/dist/generators/all.js +2 -1
- package/dist/generators/all.js.map +1 -1
- package/dist/generators/doc-parser.d.ts +49 -0
- package/dist/generators/doc-parser.d.ts.map +1 -0
- package/dist/generators/doc-parser.js +336 -0
- package/dist/generators/doc-parser.js.map +1 -0
- package/dist/generators/templates/index.d.ts +4 -0
- package/dist/generators/templates/index.d.ts.map +1 -1
- package/dist/generators/templates/index.js +4 -0
- package/dist/generators/templates/index.js.map +1 -1
- package/dist/generators/templates/website-components.d.ts +33 -0
- package/dist/generators/templates/website-components.d.ts.map +1 -0
- package/dist/generators/templates/website-components.js +278 -0
- package/dist/generators/templates/website-components.js.map +1 -0
- package/dist/generators/templates/website-config.d.ts +41 -0
- package/dist/generators/templates/website-config.d.ts.map +1 -0
- package/dist/generators/templates/website-config.js +283 -0
- package/dist/generators/templates/website-config.js.map +1 -0
- package/dist/generators/templates/website-conversion.d.ts +27 -0
- package/dist/generators/templates/website-conversion.d.ts.map +1 -0
- package/dist/generators/templates/website-conversion.js +326 -0
- package/dist/generators/templates/website-conversion.js.map +1 -0
- package/dist/generators/templates/website-seo.d.ts +76 -0
- package/dist/generators/templates/website-seo.d.ts.map +1 -0
- package/dist/generators/templates/website-seo.js +326 -0
- package/dist/generators/templates/website-seo.js.map +1 -0
- package/dist/generators/templates/website.d.ts +14 -47
- package/dist/generators/templates/website.d.ts.map +1 -1
- package/dist/generators/templates/website.js +412 -499
- package/dist/generators/templates/website.js.map +1 -1
- package/dist/generators/website-context.d.ts +83 -0
- package/dist/generators/website-context.d.ts.map +1 -0
- package/dist/generators/website-context.js +190 -0
- package/dist/generators/website-context.js.map +1 -0
- package/dist/generators/website.d.ts +3 -0
- package/dist/generators/website.d.ts.map +1 -1
- package/dist/generators/website.js +73 -10
- package/dist/generators/website.js.map +1 -1
- package/dist/state/index.d.ts +27 -0
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +30 -0
- package/dist/state/index.js.map +1 -1
- package/dist/types/consensus.d.ts +3 -0
- package/dist/types/consensus.d.ts.map +1 -1
- package/dist/types/consensus.js +1 -0
- package/dist/types/consensus.js.map +1 -1
- package/dist/types/website-strategy.d.ts +263 -0
- package/dist/types/website-strategy.d.ts.map +1 -0
- package/dist/types/website-strategy.js +105 -0
- package/dist/types/website-strategy.js.map +1 -0
- package/dist/types/workflow.d.ts +15 -0
- package/dist/types/workflow.d.ts.map +1 -1
- package/dist/types/workflow.js +6 -0
- package/dist/types/workflow.js.map +1 -1
- package/dist/workflow/consensus.d.ts.map +1 -1
- package/dist/workflow/consensus.js +2 -0
- package/dist/workflow/consensus.js.map +1 -1
- package/dist/workflow/execution-mode.d.ts.map +1 -1
- package/dist/workflow/execution-mode.js +18 -0
- package/dist/workflow/execution-mode.js.map +1 -1
- package/dist/workflow/index.d.ts +3 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +25 -0
- package/dist/workflow/index.js.map +1 -1
- package/dist/workflow/overview.d.ts +89 -0
- package/dist/workflow/overview.d.ts.map +1 -0
- package/dist/workflow/overview.js +354 -0
- package/dist/workflow/overview.js.map +1 -0
- package/dist/workflow/plan-mode.d.ts +2 -1
- package/dist/workflow/plan-mode.d.ts.map +1 -1
- package/dist/workflow/plan-mode.js +83 -5
- package/dist/workflow/plan-mode.js.map +1 -1
- package/dist/workflow/website-strategy.d.ts +70 -0
- package/dist/workflow/website-strategy.d.ts.map +1 -0
- package/dist/workflow/website-strategy.js +238 -0
- package/dist/workflow/website-strategy.js.map +1 -0
- package/dist/workflow/website-updater.d.ts +17 -0
- package/dist/workflow/website-updater.d.ts.map +1 -0
- package/dist/workflow/website-updater.js +105 -0
- package/dist/workflow/website-updater.js.map +1 -0
- package/dist/workflow/workflow-logger.d.ts +1 -1
- package/dist/workflow/workflow-logger.d.ts.map +1 -1
- package/dist/workflow/workflow-logger.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/gemini.ts +10 -4
- package/src/adapters/grok.ts +10 -4
- package/src/adapters/openai.ts +38 -6
- package/src/cli/interactive.ts +47 -0
- package/src/generators/all.ts +6 -1
- package/src/generators/doc-parser.ts +372 -0
- package/src/generators/templates/index.ts +4 -0
- package/src/generators/templates/website-components.ts +305 -0
- package/src/generators/templates/website-config.ts +291 -0
- package/src/generators/templates/website-conversion.ts +341 -0
- package/src/generators/templates/website-seo.ts +370 -0
- package/src/generators/templates/website.ts +451 -505
- package/src/generators/website-context.ts +265 -0
- package/src/generators/website.ts +109 -19
- package/src/state/index.ts +42 -0
- package/src/types/consensus.ts +3 -0
- package/src/types/website-strategy.ts +243 -0
- package/src/types/workflow.ts +15 -0
- package/src/workflow/consensus.ts +2 -0
- package/src/workflow/execution-mode.ts +21 -0
- package/src/workflow/index.ts +25 -0
- package/src/workflow/overview.ts +469 -0
- package/src/workflow/plan-mode.ts +115 -4
- package/src/workflow/website-strategy.ts +305 -0
- package/src/workflow/website-updater.ts +131 -0
- package/src/workflow/workflow-logger.ts +1 -0
- package/tests/adapters/persona-switching.test.ts +63 -0
- package/tests/generators/website-components.test.ts +159 -0
- package/tests/generators/website-context.test.ts +222 -0
- package/tests/generators/website-seo-quality.test.ts +246 -0
- package/tests/workflow/overview.test.ts +392 -0
- package/tests/workflow/website-strategy.test.ts +191 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Website strategy type definitions
|
|
3
|
+
* Defines the strategic marketing document, site architecture,
|
|
4
|
+
* design tokens, and brand assets contract for website generation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Navigation item for site header/footer
|
|
11
|
+
*/
|
|
12
|
+
export interface NavItem {
|
|
13
|
+
label: string;
|
|
14
|
+
href: string;
|
|
15
|
+
children?: NavItem[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Footer section with links
|
|
20
|
+
*/
|
|
21
|
+
export interface FooterSection {
|
|
22
|
+
title: string;
|
|
23
|
+
links: Array<{ label: string; href: string }>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Page definition in site architecture
|
|
28
|
+
*/
|
|
29
|
+
export interface SiteArchitecturePage {
|
|
30
|
+
path: string;
|
|
31
|
+
title: string;
|
|
32
|
+
purpose: string;
|
|
33
|
+
pageType:
|
|
34
|
+
| 'landing'
|
|
35
|
+
| 'pricing'
|
|
36
|
+
| 'solution'
|
|
37
|
+
| 'use-cases'
|
|
38
|
+
| 'about'
|
|
39
|
+
| 'contact'
|
|
40
|
+
| 'blog'
|
|
41
|
+
| 'docs'
|
|
42
|
+
| 'legal';
|
|
43
|
+
sections: string[];
|
|
44
|
+
seoKeywords: string[];
|
|
45
|
+
conversionGoal: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Complete website strategy document
|
|
50
|
+
* Generated by AI from product context, user docs, and market inputs
|
|
51
|
+
*/
|
|
52
|
+
export interface WebsiteStrategyDocument {
|
|
53
|
+
icp: {
|
|
54
|
+
primaryPersona: string;
|
|
55
|
+
painPoints: string[];
|
|
56
|
+
goals: string[];
|
|
57
|
+
objections: string[];
|
|
58
|
+
};
|
|
59
|
+
positioning: {
|
|
60
|
+
category: string;
|
|
61
|
+
differentiators: string[];
|
|
62
|
+
valueProposition: string;
|
|
63
|
+
proofPoints: string[];
|
|
64
|
+
};
|
|
65
|
+
messaging: {
|
|
66
|
+
headline: string;
|
|
67
|
+
subheadline: string;
|
|
68
|
+
elevatorPitch: string;
|
|
69
|
+
longDescription: string;
|
|
70
|
+
};
|
|
71
|
+
seoStrategy: {
|
|
72
|
+
primaryKeywords: string[];
|
|
73
|
+
secondaryKeywords: string[];
|
|
74
|
+
longTailKeywords: string[];
|
|
75
|
+
titleTemplates: Record<string, string>;
|
|
76
|
+
metaDescriptions: Record<string, string>;
|
|
77
|
+
};
|
|
78
|
+
siteArchitecture: {
|
|
79
|
+
pages: SiteArchitecturePage[];
|
|
80
|
+
navigation: NavItem[];
|
|
81
|
+
footerSections: FooterSection[];
|
|
82
|
+
};
|
|
83
|
+
conversionStrategy: {
|
|
84
|
+
primaryCta: { text: string; href: string };
|
|
85
|
+
secondaryCta: { text: string; href: string };
|
|
86
|
+
trustSignals: string[];
|
|
87
|
+
socialProof: string[];
|
|
88
|
+
leadCapture: 'none' | 'webhook' | 'resend' | 'postmark';
|
|
89
|
+
};
|
|
90
|
+
competitiveContext: {
|
|
91
|
+
category: string;
|
|
92
|
+
competitors: string[];
|
|
93
|
+
differentiators: string[];
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Strategy metadata for caching and staleness detection
|
|
99
|
+
*/
|
|
100
|
+
export interface StrategyMetadata {
|
|
101
|
+
/** SHA-256 of (docs + spec + tokens) for staleness detection */
|
|
102
|
+
inputHash: string;
|
|
103
|
+
/** ISO timestamp of generation */
|
|
104
|
+
generatedAt: string;
|
|
105
|
+
/** Schema version */
|
|
106
|
+
version: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Design tokens extracted from project config or brand docs
|
|
111
|
+
*/
|
|
112
|
+
export interface DesignTokens {
|
|
113
|
+
colors: Record<string, string>;
|
|
114
|
+
fonts: { heading: string; body: string; mono?: string };
|
|
115
|
+
borderRadius: string;
|
|
116
|
+
source: 'tailwind-config' | 'css-variables' | 'brand-docs' | 'defaults';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Brand assets contract for deterministic logo/favicon placement
|
|
121
|
+
*/
|
|
122
|
+
export interface BrandAssetsContract {
|
|
123
|
+
/** Discovered source path for logo */
|
|
124
|
+
logoPath?: string;
|
|
125
|
+
/** Canonical output path: public/brand/logo.{ext} */
|
|
126
|
+
logoOutputPath: string;
|
|
127
|
+
/** Discovered source path for favicon */
|
|
128
|
+
faviconPath?: string;
|
|
129
|
+
/** Primary brand color */
|
|
130
|
+
primaryColor?: string;
|
|
131
|
+
/** Full color scheme */
|
|
132
|
+
colorScheme?: Record<string, string>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// --- Zod Schemas ---
|
|
136
|
+
|
|
137
|
+
export const NavItemSchema: z.ZodType<NavItem> = z.lazy(() =>
|
|
138
|
+
z.object({
|
|
139
|
+
label: z.string().min(1),
|
|
140
|
+
href: z.string().min(1),
|
|
141
|
+
children: z.array(NavItemSchema).optional(),
|
|
142
|
+
})
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
export const FooterSectionSchema = z.object({
|
|
146
|
+
title: z.string().min(1),
|
|
147
|
+
links: z.array(
|
|
148
|
+
z.object({
|
|
149
|
+
label: z.string().min(1),
|
|
150
|
+
href: z.string().min(1),
|
|
151
|
+
})
|
|
152
|
+
),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
export const SiteArchitecturePageSchema = z.object({
|
|
156
|
+
path: z.string().min(1),
|
|
157
|
+
title: z.string().min(1),
|
|
158
|
+
purpose: z.string(),
|
|
159
|
+
pageType: z.enum([
|
|
160
|
+
'landing',
|
|
161
|
+
'pricing',
|
|
162
|
+
'solution',
|
|
163
|
+
'use-cases',
|
|
164
|
+
'about',
|
|
165
|
+
'contact',
|
|
166
|
+
'blog',
|
|
167
|
+
'docs',
|
|
168
|
+
'legal',
|
|
169
|
+
]),
|
|
170
|
+
sections: z.array(z.string()),
|
|
171
|
+
seoKeywords: z.array(z.string()),
|
|
172
|
+
conversionGoal: z.string(),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
export const WebsiteStrategySchema = z.object({
|
|
176
|
+
icp: z.object({
|
|
177
|
+
primaryPersona: z.string().min(1),
|
|
178
|
+
painPoints: z.array(z.string()),
|
|
179
|
+
goals: z.array(z.string()),
|
|
180
|
+
objections: z.array(z.string()),
|
|
181
|
+
}),
|
|
182
|
+
positioning: z.object({
|
|
183
|
+
category: z.string().min(1),
|
|
184
|
+
differentiators: z.array(z.string()),
|
|
185
|
+
valueProposition: z.string().min(1),
|
|
186
|
+
proofPoints: z.array(z.string()),
|
|
187
|
+
}),
|
|
188
|
+
messaging: z.object({
|
|
189
|
+
headline: z.string().min(1),
|
|
190
|
+
subheadline: z.string().min(1),
|
|
191
|
+
elevatorPitch: z.string().min(1),
|
|
192
|
+
longDescription: z.string().min(1),
|
|
193
|
+
}),
|
|
194
|
+
seoStrategy: z.object({
|
|
195
|
+
primaryKeywords: z.array(z.string()),
|
|
196
|
+
secondaryKeywords: z.array(z.string()),
|
|
197
|
+
longTailKeywords: z.array(z.string()),
|
|
198
|
+
titleTemplates: z.record(z.string(), z.string()),
|
|
199
|
+
metaDescriptions: z.record(z.string(), z.string()),
|
|
200
|
+
}),
|
|
201
|
+
siteArchitecture: z.object({
|
|
202
|
+
pages: z.array(SiteArchitecturePageSchema),
|
|
203
|
+
navigation: z.array(NavItemSchema),
|
|
204
|
+
footerSections: z.array(FooterSectionSchema),
|
|
205
|
+
}),
|
|
206
|
+
conversionStrategy: z.object({
|
|
207
|
+
primaryCta: z.object({ text: z.string().min(1), href: z.string().min(1) }),
|
|
208
|
+
secondaryCta: z.object({ text: z.string().min(1), href: z.string().min(1) }),
|
|
209
|
+
trustSignals: z.array(z.string()),
|
|
210
|
+
socialProof: z.array(z.string()),
|
|
211
|
+
leadCapture: z.enum(['none', 'webhook', 'resend', 'postmark']),
|
|
212
|
+
}),
|
|
213
|
+
competitiveContext: z.object({
|
|
214
|
+
category: z.string(),
|
|
215
|
+
competitors: z.array(z.string()),
|
|
216
|
+
differentiators: z.array(z.string()),
|
|
217
|
+
}),
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export const StrategyMetadataSchema = z.object({
|
|
221
|
+
inputHash: z.string().min(1),
|
|
222
|
+
generatedAt: z.string().min(1),
|
|
223
|
+
version: z.number(),
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
export const DesignTokensSchema = z.object({
|
|
227
|
+
colors: z.record(z.string(), z.string()),
|
|
228
|
+
fonts: z.object({
|
|
229
|
+
heading: z.string(),
|
|
230
|
+
body: z.string(),
|
|
231
|
+
mono: z.string().optional(),
|
|
232
|
+
}),
|
|
233
|
+
borderRadius: z.string(),
|
|
234
|
+
source: z.enum(['tailwind-config', 'css-variables', 'brand-docs', 'defaults']),
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
export const BrandAssetsContractSchema = z.object({
|
|
238
|
+
logoPath: z.string().optional(),
|
|
239
|
+
logoOutputPath: z.string().min(1),
|
|
240
|
+
faviconPath: z.string().optional(),
|
|
241
|
+
primaryColor: z.string().optional(),
|
|
242
|
+
colorScheme: z.record(z.string(), z.string()).optional(),
|
|
243
|
+
});
|
package/src/types/workflow.ts
CHANGED
|
@@ -192,6 +192,15 @@ export interface ProjectState {
|
|
|
192
192
|
error?: string;
|
|
193
193
|
createdAt: string;
|
|
194
194
|
updatedAt: string;
|
|
195
|
+
/** Raw user documentation discovered from CWD */
|
|
196
|
+
userDocs?: string;
|
|
197
|
+
/** Brand context discovered from CWD */
|
|
198
|
+
brandContext?: {
|
|
199
|
+
logoPath?: string;
|
|
200
|
+
primaryColor?: string;
|
|
201
|
+
};
|
|
202
|
+
/** Path to website strategy JSON file (relative to .popeye/) */
|
|
203
|
+
websiteStrategy?: string;
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
/**
|
|
@@ -229,6 +238,12 @@ export const ProjectStateSchema = z.object({
|
|
|
229
238
|
error: z.string().optional(),
|
|
230
239
|
createdAt: z.string(),
|
|
231
240
|
updatedAt: z.string(),
|
|
241
|
+
userDocs: z.string().optional(),
|
|
242
|
+
brandContext: z.object({
|
|
243
|
+
logoPath: z.string().optional(),
|
|
244
|
+
primaryColor: z.string().optional(),
|
|
245
|
+
}).optional(),
|
|
246
|
+
websiteStrategy: z.string().optional(),
|
|
232
247
|
});
|
|
233
248
|
|
|
234
249
|
/**
|
|
@@ -79,6 +79,7 @@ async function requestReviewerConsensus(
|
|
|
79
79
|
model: config.geminiModel,
|
|
80
80
|
temperature: config.temperature,
|
|
81
81
|
maxTokens: config.maxTokens,
|
|
82
|
+
reviewerPersona: config.reviewerPersona,
|
|
82
83
|
});
|
|
83
84
|
}
|
|
84
85
|
if (reviewer === 'grok') {
|
|
@@ -86,6 +87,7 @@ async function requestReviewerConsensus(
|
|
|
86
87
|
model: config.grokModel,
|
|
87
88
|
temperature: config.temperature,
|
|
88
89
|
maxTokens: config.maxTokens,
|
|
90
|
+
reviewerPersona: config.reviewerPersona,
|
|
89
91
|
});
|
|
90
92
|
}
|
|
91
93
|
return requestOpenAIConsensus(plan, context, config);
|
|
@@ -782,6 +782,14 @@ function buildTaskContext(
|
|
|
782
782
|
): string {
|
|
783
783
|
const lines: string[] = [];
|
|
784
784
|
|
|
785
|
+
// No-hardcode enforcement rule
|
|
786
|
+
lines.push('## CRITICAL RULES');
|
|
787
|
+
lines.push('- NEVER use hardcoded placeholder content, mock data, or invented copy.');
|
|
788
|
+
lines.push('- ALL text, features, pricing, colors, and data MUST come from the project specification and user documentation below.');
|
|
789
|
+
lines.push('- If information is not available in the spec, leave a TODO comment rather than inventing content.');
|
|
790
|
+
lines.push('- Do NOT hallucinate product names, features, pricing tiers, testimonials, or blog content.');
|
|
791
|
+
lines.push('');
|
|
792
|
+
|
|
785
793
|
lines.push(`## Project: ${state.name}`);
|
|
786
794
|
lines.push(`Language: ${state.language}`);
|
|
787
795
|
lines.push('');
|
|
@@ -798,6 +806,19 @@ function buildTaskContext(
|
|
|
798
806
|
lines.push('');
|
|
799
807
|
}
|
|
800
808
|
|
|
809
|
+
// Include user documentation if available
|
|
810
|
+
if (state.userDocs) {
|
|
811
|
+
lines.push('## Project Documentation');
|
|
812
|
+
lines.push(state.userDocs.slice(0, 3000));
|
|
813
|
+
lines.push('');
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// Include brand context if available
|
|
817
|
+
if (state.brandContext?.primaryColor) {
|
|
818
|
+
lines.push(`## Brand: Primary color ${state.brandContext.primaryColor}`);
|
|
819
|
+
lines.push('');
|
|
820
|
+
}
|
|
821
|
+
|
|
801
822
|
// Include UI design context if available
|
|
802
823
|
if (uiDesignContext) {
|
|
803
824
|
lines.push(uiDesignContext);
|
package/src/workflow/index.ts
CHANGED
|
@@ -50,6 +50,9 @@ export * from './task-workflow.js';
|
|
|
50
50
|
export * from './milestone-workflow.js';
|
|
51
51
|
export * from './plan-storage.js';
|
|
52
52
|
export * from './workspace-manager.js';
|
|
53
|
+
export * from './website-updater.js';
|
|
54
|
+
export * from './website-strategy.js';
|
|
55
|
+
export * from './overview.js';
|
|
53
56
|
|
|
54
57
|
/**
|
|
55
58
|
* Workflow options
|
|
@@ -116,6 +119,17 @@ export async function runWorkflow(
|
|
|
116
119
|
};
|
|
117
120
|
}
|
|
118
121
|
|
|
122
|
+
// Post-plan: Update website content with project context
|
|
123
|
+
if (spec.language === 'website' || spec.language === 'all' || spec.language === 'fullstack') {
|
|
124
|
+
try {
|
|
125
|
+
onProgress?.('website-update', 'Updating website with project context...');
|
|
126
|
+
const { updateWebsiteContent } = await import('./website-updater.js');
|
|
127
|
+
await updateWebsiteContent(projectDir, planResult.state, spec.language, (msg) => onProgress?.('website-update', msg));
|
|
128
|
+
} catch {
|
|
129
|
+
// Non-blocking: website content update failure should not stop workflow
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
119
133
|
// Phase 2: Execution Mode
|
|
120
134
|
onProgress?.('workflow', 'Starting Execution Mode...');
|
|
121
135
|
|
|
@@ -224,6 +238,17 @@ export async function resumeWorkflow(
|
|
|
224
238
|
};
|
|
225
239
|
}
|
|
226
240
|
|
|
241
|
+
// Post-plan: Update website content with project context
|
|
242
|
+
if (state.language === 'website' || state.language === 'all' || state.language === 'fullstack') {
|
|
243
|
+
try {
|
|
244
|
+
onProgress?.('website-update', 'Updating website with project context...');
|
|
245
|
+
const { updateWebsiteContent } = await import('./website-updater.js');
|
|
246
|
+
await updateWebsiteContent(projectDir, planResult.state, state.language, (msg) => onProgress?.('website-update', msg));
|
|
247
|
+
} catch {
|
|
248
|
+
// Non-blocking
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
227
252
|
// Continue to execution
|
|
228
253
|
onProgress?.('workflow', 'Starting Execution Mode...');
|
|
229
254
|
|