@getcoherent/cli 0.6.55 → 0.6.57
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/{chunk-IFJK5OPI.js → chunk-BNHIEEXH.js} +1 -1
- package/dist/{chunk-NLL3SHN3.js → chunk-PVVL26FX.js} +4 -3
- package/dist/{chunk-UZGT5APM.js → chunk-XBX4WND7.js} +2 -2
- package/dist/{code-generator-IZ6XM6WG.js → code-generator-SKXX6PQG.js} +3 -3
- package/dist/{design-constraints-PFZDW2XW.js → design-constraints-PFCUSBMG.js} +1 -1
- package/dist/index.js +86 -71
- package/dist/{plan-generator-D2UBTVCN.js → plan-generator-A3YN473Q.js} +2 -2
- package/package.json +1 -1
|
@@ -1007,17 +1007,18 @@ var CONTEXTUAL_CATEGORIES = [
|
|
|
1007
1007
|
rules: RULES_SHADCN_APIS
|
|
1008
1008
|
}
|
|
1009
1009
|
];
|
|
1010
|
-
function selectContextualRules(message) {
|
|
1010
|
+
function selectContextualRules(message, pageSections) {
|
|
1011
1011
|
const matched = /* @__PURE__ */ new Set();
|
|
1012
|
+
const matchTarget = pageSections && pageSections.length > 0 ? pageSections.join(" ") : message;
|
|
1012
1013
|
for (const category of CONTEXTUAL_CATEGORIES) {
|
|
1013
|
-
if (category.keywords.test(
|
|
1014
|
+
if (category.keywords.test(matchTarget)) {
|
|
1014
1015
|
matched.add(category.rules);
|
|
1015
1016
|
}
|
|
1016
1017
|
}
|
|
1017
1018
|
if (matched.size === 0) {
|
|
1018
1019
|
return "";
|
|
1019
1020
|
}
|
|
1020
|
-
return [...matched].join("\n");
|
|
1021
|
+
return [...matched].slice(0, 3).join("\n");
|
|
1021
1022
|
}
|
|
1022
1023
|
var DESIGN_CONSTRAINTS = `${DESIGN_THINKING}
|
|
1023
1024
|
${CORE_CONSTRAINTS}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getPageGroup,
|
|
7
7
|
installPackages,
|
|
8
8
|
sanitizeMetadataStrings
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-BNHIEEXH.js";
|
|
10
10
|
import {
|
|
11
11
|
toKebabCase
|
|
12
12
|
} from "./chunk-4TLYDTT3.js";
|
|
@@ -2147,7 +2147,7 @@ async function regeneratePage(pageId, config, projectRoot) {
|
|
|
2147
2147
|
const code = await generator.generate(page, appType);
|
|
2148
2148
|
const route = page.route || "/";
|
|
2149
2149
|
const isAuth = isAuthRoute(route) || isAuthRoute(page.name || page.id || "");
|
|
2150
|
-
const { loadPlan: loadPlanForPath } = await import("./plan-generator-
|
|
2150
|
+
const { loadPlan: loadPlanForPath } = await import("./plan-generator-A3YN473Q.js");
|
|
2151
2151
|
const planForPath = loadPlanForPath(projectRoot);
|
|
2152
2152
|
const filePath = routeToFsPath(projectRoot, route, planForPath || isAuth);
|
|
2153
2153
|
await mkdir3(dirname3(filePath), { recursive: true });
|
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
regeneratePage,
|
|
13
13
|
scanAndInstallSharedDeps,
|
|
14
14
|
validateAndFixGeneratedCode
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-XBX4WND7.js";
|
|
16
|
+
import "./chunk-BNHIEEXH.js";
|
|
17
17
|
import "./chunk-4TLYDTT3.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-PVVL26FX.js";
|
|
19
19
|
import "./chunk-U5SNPHVU.js";
|
|
20
20
|
import "./chunk-3RG5ZIWI.js";
|
|
21
21
|
export {
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
warnIfVolatile,
|
|
35
35
|
warnInlineDuplicates,
|
|
36
36
|
writeFile
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-XBX4WND7.js";
|
|
38
38
|
import {
|
|
39
39
|
COHERENT_REQUIRED_PACKAGES,
|
|
40
40
|
ensureUseClientIfNeeded,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
sanitizeMetadataStrings,
|
|
53
53
|
savePlan,
|
|
54
54
|
updateArchitecturePlan
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-BNHIEEXH.js";
|
|
56
56
|
import {
|
|
57
57
|
isValidTsx,
|
|
58
58
|
safeWrite
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
getDesignQualityForType,
|
|
75
75
|
inferPageTypeFromRoute,
|
|
76
76
|
selectContextualRules
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-PVVL26FX.js";
|
|
78
78
|
import {
|
|
79
79
|
fixGlobalsCss,
|
|
80
80
|
generateV4GlobalsCss,
|
|
@@ -1830,9 +1830,9 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1830
1830
|
if (!existsSync3(componentsUiPath)) mkdirSync3(componentsUiPath, { recursive: true });
|
|
1831
1831
|
}
|
|
1832
1832
|
async function ensureRegistryComponents(config2, projectPath) {
|
|
1833
|
-
const
|
|
1833
|
+
const provider = getComponentProvider();
|
|
1834
1834
|
const baseComponents = ["button", "card", "input", "label", "switch"];
|
|
1835
|
-
await
|
|
1835
|
+
await provider.installBatch(baseComponents, projectPath);
|
|
1836
1836
|
const generator = new ComponentGenerator(config2);
|
|
1837
1837
|
const uiDir = join3(projectPath, "components", "ui");
|
|
1838
1838
|
if (!existsSync3(uiDir)) mkdirSync3(uiDir, { recursive: true });
|
|
@@ -2110,8 +2110,8 @@ import {
|
|
|
2110
2110
|
|
|
2111
2111
|
// src/agents/modifier.ts
|
|
2112
2112
|
import chalk4 from "chalk";
|
|
2113
|
-
async function parseModification(message, context,
|
|
2114
|
-
const ai = await createAIProvider(
|
|
2113
|
+
async function parseModification(message, context, provider = "auto", options) {
|
|
2114
|
+
const ai = await createAIProvider(provider);
|
|
2115
2115
|
if (options?.planOnly) {
|
|
2116
2116
|
const prompt2 = buildPlanOnlyPrompt(message, context.config);
|
|
2117
2117
|
const raw2 = await ai.parseModification(prompt2);
|
|
@@ -2143,7 +2143,8 @@ async function parseModification(message, context, provider2 = "auto", options)
|
|
|
2143
2143
|
isExpandedPageRequest,
|
|
2144
2144
|
sharedComponentsSummary: options?.sharedComponentsSummary,
|
|
2145
2145
|
tieredComponentsPrompt: options?.tieredComponentsPrompt,
|
|
2146
|
-
reusePlanDirective: options?.reusePlanDirective
|
|
2146
|
+
reusePlanDirective: options?.reusePlanDirective,
|
|
2147
|
+
pageSections: options?.pageSections
|
|
2147
2148
|
});
|
|
2148
2149
|
const raw = await ai.parseModification(prompt);
|
|
2149
2150
|
const requestsArray = Array.isArray(raw) ? raw : raw?.requests ?? [];
|
|
@@ -2243,7 +2244,7 @@ For editing an existing shared component use type "modify-layout-block" with tar
|
|
|
2243
2244
|
const coreRules = CORE_CONSTRAINTS;
|
|
2244
2245
|
const designQuality = DESIGN_QUALITY;
|
|
2245
2246
|
const visualDepth = VISUAL_DEPTH;
|
|
2246
|
-
const contextualRules = selectContextualRules(message);
|
|
2247
|
+
const contextualRules = selectContextualRules(message, options?.pageSections);
|
|
2247
2248
|
const interactionPatterns = INTERACTION_PATTERNS;
|
|
2248
2249
|
const light = config2.tokens.colors.light;
|
|
2249
2250
|
const dark = config2.tokens.colors.dark;
|
|
@@ -3511,12 +3512,24 @@ function verifyReusePlan(generatedCode, plan) {
|
|
|
3511
3512
|
}
|
|
3512
3513
|
|
|
3513
3514
|
// src/commands/chat/split-generator.ts
|
|
3514
|
-
var MAX_EXISTING_PAGES_CONTEXT =
|
|
3515
|
-
function
|
|
3515
|
+
var MAX_EXISTING_PAGES_CONTEXT = 3;
|
|
3516
|
+
function filterManifestForPage(manifest, plan, route) {
|
|
3517
|
+
const plannedForPage = plan.sharedComponents.filter((c) => c.usedBy.includes(route)).map((c) => c.name.toLowerCase());
|
|
3518
|
+
if (plannedForPage.length === 0) return manifest;
|
|
3519
|
+
const filtered = manifest.shared.filter((e) => plannedForPage.includes(e.name.toLowerCase()) || e.type === "layout");
|
|
3520
|
+
if (filtered.length === 0) return manifest;
|
|
3521
|
+
return { ...manifest, shared: filtered };
|
|
3522
|
+
}
|
|
3523
|
+
function buildExistingPagesContext(config2, forPageType) {
|
|
3516
3524
|
const pages = config2.pages || [];
|
|
3517
3525
|
const analyzed = pages.filter((p) => p.pageAnalysis);
|
|
3518
3526
|
if (analyzed.length === 0) return "";
|
|
3519
|
-
|
|
3527
|
+
let relevant = analyzed;
|
|
3528
|
+
if (forPageType) {
|
|
3529
|
+
const sameType = analyzed.filter((p) => inferPageTypeFromRoute(p.route) === forPageType);
|
|
3530
|
+
relevant = sameType.length > 0 ? sameType : analyzed;
|
|
3531
|
+
}
|
|
3532
|
+
const capped = relevant.slice(0, MAX_EXISTING_PAGES_CONTEXT);
|
|
3520
3533
|
const lines = capped.map((p) => {
|
|
3521
3534
|
return summarizePageAnalysis(p.name || p.id, p.route, p.pageAnalysis);
|
|
3522
3535
|
});
|
|
@@ -3781,11 +3794,11 @@ async function updateManifestSafe(projectRoot, fn) {
|
|
|
3781
3794
|
]).catch(() => {
|
|
3782
3795
|
});
|
|
3783
3796
|
}
|
|
3784
|
-
async function splitGeneratePages(spinner, message, modCtx,
|
|
3797
|
+
async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts) {
|
|
3785
3798
|
let pageNames = [];
|
|
3786
3799
|
spinner.start("Phase 1/6 \u2014 Planning pages...");
|
|
3787
3800
|
try {
|
|
3788
|
-
const planResult = await parseModification(message, modCtx,
|
|
3801
|
+
const planResult = await parseModification(message, modCtx, provider, { ...parseOpts, planOnly: true });
|
|
3789
3802
|
const pageReqs = planResult.requests.filter((r) => r.type === "add-page");
|
|
3790
3803
|
pageNames = pageReqs.map((r) => {
|
|
3791
3804
|
const c = r.changes;
|
|
@@ -3845,7 +3858,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider2, parseOpts
|
|
|
3845
3858
|
if (parseOpts.projectRoot) {
|
|
3846
3859
|
spinner.start("Phase 2/6 \u2014 Generating architecture plan...");
|
|
3847
3860
|
try {
|
|
3848
|
-
const ai = await createAIProvider(
|
|
3861
|
+
const ai = await createAIProvider(provider ?? "auto");
|
|
3849
3862
|
const cachedPlan = loadPlan(parseOpts.projectRoot);
|
|
3850
3863
|
let planWarnings = [];
|
|
3851
3864
|
if (cachedPlan) {
|
|
@@ -3907,7 +3920,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider2, parseOpts
|
|
|
3907
3920
|
spinner.start(`Phase 3/6 \u2014 Generating ${homePage.name} page (sets design direction)...`);
|
|
3908
3921
|
try {
|
|
3909
3922
|
const anchorPrompt = buildAnchorPagePrompt(homePage, message, allPagesList, allRoutes, plan);
|
|
3910
|
-
const homeResult = await parseModification(anchorPrompt, modCtx,
|
|
3923
|
+
const homeResult = await parseModification(anchorPrompt, modCtx, provider, parseOpts);
|
|
3911
3924
|
const codePage = homeResult.requests.find((r) => r.type === "add-page");
|
|
3912
3925
|
if (codePage) {
|
|
3913
3926
|
homeRequest = codePage;
|
|
@@ -3941,12 +3954,12 @@ async function splitGeneratePages(spinner, message, modCtx, provider2, parseOpts
|
|
|
3941
3954
|
if (plan && plan.sharedComponents.length > 0) {
|
|
3942
3955
|
spinner.start(`Phase 4.5/6 \u2014 Generating ${plan.sharedComponents.length} shared components from plan...`);
|
|
3943
3956
|
try {
|
|
3944
|
-
const { generateSharedComponentsFromPlan } = await import("./plan-generator-
|
|
3957
|
+
const { generateSharedComponentsFromPlan } = await import("./plan-generator-A3YN473Q.js");
|
|
3945
3958
|
const generated = await generateSharedComponentsFromPlan(
|
|
3946
3959
|
plan,
|
|
3947
3960
|
styleContext,
|
|
3948
3961
|
projectRoot,
|
|
3949
|
-
await createAIProvider(
|
|
3962
|
+
await createAIProvider(provider ?? "auto")
|
|
3950
3963
|
);
|
|
3951
3964
|
if (generated.length > 0) {
|
|
3952
3965
|
const updatedManifest = await loadManifest3(projectRoot);
|
|
@@ -3965,7 +3978,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider2, parseOpts
|
|
|
3965
3978
|
if (!shouldSkip) {
|
|
3966
3979
|
spinner.start("Phase 4.5/6 \u2014 Extracting shared components (legacy)...");
|
|
3967
3980
|
try {
|
|
3968
|
-
const extraction = await extractSharedComponents(homePageCode, projectRoot,
|
|
3981
|
+
const extraction = await extractSharedComponents(homePageCode, projectRoot, provider ?? "auto");
|
|
3969
3982
|
parseOpts.sharedComponentsSummary = extraction.summary;
|
|
3970
3983
|
if (extraction.components.length > 0) {
|
|
3971
3984
|
const names = extraction.components.map((c) => c.name).join(", ");
|
|
@@ -3994,7 +4007,6 @@ EXISTING APP PAGE (match these UI patterns for consistency):
|
|
|
3994
4007
|
${existingAppPageCode}
|
|
3995
4008
|
\`\`\`
|
|
3996
4009
|
` : "";
|
|
3997
|
-
const existingPagesContext = buildExistingPagesContext(modCtx.config);
|
|
3998
4010
|
const existingPageCode = {};
|
|
3999
4011
|
if (projectRoot) {
|
|
4000
4012
|
const appDir = resolve2(projectRoot, "app");
|
|
@@ -4021,9 +4033,11 @@ ${existingAppPageCode}
|
|
|
4021
4033
|
const pageType = plan ? getPageType(route, plan) : inferPageTypeFromRoute(route);
|
|
4022
4034
|
const designConstraints = getDesignQualityForType(pageType);
|
|
4023
4035
|
const authNote = isAuth ? 'For this auth page: the auth layout already provides centering (flex items-center justify-center min-h-svh). Do NOT add your own centering wrapper or min-h-svh. Just output a div with className="w-full max-w-md" containing the Card. Do NOT use section containers or full-width wrappers.' : void 0;
|
|
4036
|
+
const existingPagesContext = buildExistingPagesContext(modCtx.config, pageType);
|
|
4024
4037
|
const layoutForPage = getGroupLayoutForRoute(route, plan);
|
|
4025
4038
|
const layoutNote = buildLayoutNote(layoutForPage);
|
|
4026
|
-
const
|
|
4039
|
+
const filteredManifest = currentManifest && plan ? filterManifestForPage(currentManifest, plan, route) : currentManifest;
|
|
4040
|
+
const tieredNote = filteredManifest ? buildTieredComponentsPrompt(filteredManifest, pageType) : void 0;
|
|
4027
4041
|
const pageKey = route.replace(/^\//, "") || "home";
|
|
4028
4042
|
const pageSections = plan?.pageNotes?.[pageKey]?.sections || [];
|
|
4029
4043
|
let reusePlanDirective = "";
|
|
@@ -4070,7 +4084,7 @@ ${existingAppPageCode}
|
|
|
4070
4084
|
styleContext
|
|
4071
4085
|
].filter(Boolean).join("\n\n");
|
|
4072
4086
|
try {
|
|
4073
|
-
const result = await parseModification(prompt, modCtx,
|
|
4087
|
+
const result = await parseModification(prompt, modCtx, provider, { ...parseOpts, pageSections });
|
|
4074
4088
|
phase5Done++;
|
|
4075
4089
|
spinner.text = `Phase 5/6 \u2014 ${phase5Done}/${remainingPages.length} pages generated...`;
|
|
4076
4090
|
const codePage = result.requests.find((r) => r.type === "add-page");
|
|
@@ -4087,7 +4101,7 @@ ${existingAppPageCode}
|
|
|
4087
4101
|
const missedNames = verification.missed.map((m) => m.component);
|
|
4088
4102
|
console.log(chalk6.yellow(` \u26A0 Missed reuse in "${name}": ${missedNames.join(", ")} \u2014 patching...`));
|
|
4089
4103
|
try {
|
|
4090
|
-
const ai = await createAIProvider(
|
|
4104
|
+
const ai = await createAIProvider(provider);
|
|
4091
4105
|
if (ai.editPageCode) {
|
|
4092
4106
|
const patchLines = verification.missed.map((m) => {
|
|
4093
4107
|
const importPath = m.importPath || `@/components/shared/${m.component.replace(/([A-Z])/g, (_, c, i) => (i ? "-" : "") + c.toLowerCase()).replace(/^-/, "")}`;
|
|
@@ -4153,7 +4167,7 @@ Keep all existing functionality. Only add imports and replace inline duplicates.
|
|
|
4153
4167
|
retryPageType,
|
|
4154
4168
|
retryTieredNote
|
|
4155
4169
|
);
|
|
4156
|
-
const retryResult = await parseModification(lightweightPrompt, modCtx,
|
|
4170
|
+
const retryResult = await parseModification(lightweightPrompt, modCtx, provider, {
|
|
4157
4171
|
...parseOpts,
|
|
4158
4172
|
lightweight: true
|
|
4159
4173
|
});
|
|
@@ -4219,14 +4233,14 @@ async function extractSharedComponents(homePageCode, projectRoot, aiProvider) {
|
|
|
4219
4233
|
return true;
|
|
4220
4234
|
});
|
|
4221
4235
|
const results = [];
|
|
4222
|
-
const
|
|
4236
|
+
const provider = getComponentProvider();
|
|
4223
4237
|
for (const item of filtered) {
|
|
4224
4238
|
try {
|
|
4225
4239
|
let { code: fixedCode } = await autoFixCode(item.code);
|
|
4226
4240
|
fixedCode = fixedCode.replace(/export default function (\w+)/g, "export function $1");
|
|
4227
4241
|
const shadcnImports = [...fixedCode.matchAll(/from\s+["']@\/components\/ui\/(.+?)["']/g)];
|
|
4228
4242
|
for (const match of shadcnImports) {
|
|
4229
|
-
await
|
|
4243
|
+
await provider.installComponent(match[1], projectRoot);
|
|
4230
4244
|
}
|
|
4231
4245
|
const result = await generateSharedComponent2(projectRoot, {
|
|
4232
4246
|
name: item.name,
|
|
@@ -4915,9 +4929,9 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
|
|
|
4915
4929
|
}
|
|
4916
4930
|
case "add-component": {
|
|
4917
4931
|
const componentData = request.changes;
|
|
4918
|
-
const
|
|
4919
|
-
if (componentData.source === "shadcn" &&
|
|
4920
|
-
const result2 = await
|
|
4932
|
+
const provider = getComponentProvider();
|
|
4933
|
+
if (componentData.source === "shadcn" && provider.has(componentData.id)) {
|
|
4934
|
+
const result2 = await provider.installComponent(componentData.id, projectRoot);
|
|
4921
4935
|
if (result2.success && result2.componentDef) {
|
|
4922
4936
|
const mergedData = {
|
|
4923
4937
|
...result2.componentDef,
|
|
@@ -5628,8 +5642,8 @@ async function interactiveChat(options, chatCommandFn) {
|
|
|
5628
5642
|
await dsm.load();
|
|
5629
5643
|
const cm = new ComponentManager3(config2);
|
|
5630
5644
|
const validProviders = ["claude", "openai", "auto"];
|
|
5631
|
-
const
|
|
5632
|
-
if (!validProviders.includes(
|
|
5645
|
+
const provider = (options.provider || "auto").toLowerCase();
|
|
5646
|
+
if (!validProviders.includes(provider)) {
|
|
5633
5647
|
console.error(chalk9.red(`
|
|
5634
5648
|
\u274C Invalid provider: ${options.provider}`));
|
|
5635
5649
|
process.exit(1);
|
|
@@ -5774,7 +5788,7 @@ async function interactiveChat(options, chatCommandFn) {
|
|
|
5774
5788
|
resolvedInput = componentMatch[2];
|
|
5775
5789
|
}
|
|
5776
5790
|
try {
|
|
5777
|
-
await chatCommandFn(resolvedInput, { provider
|
|
5791
|
+
await chatCommandFn(resolvedInput, { provider, interactive: false, _throwOnError: true, ...extraOpts });
|
|
5778
5792
|
await dsm.load();
|
|
5779
5793
|
} catch (err) {
|
|
5780
5794
|
if (!err._printed) {
|
|
@@ -5825,11 +5839,11 @@ async function chatCommand(message, options) {
|
|
|
5825
5839
|
bail("Migration in progress");
|
|
5826
5840
|
}
|
|
5827
5841
|
const validProviders = ["claude", "openai", "auto"];
|
|
5828
|
-
const
|
|
5842
|
+
const provider = (options.provider || "auto").toLowerCase();
|
|
5829
5843
|
let releaseLock;
|
|
5830
5844
|
try {
|
|
5831
5845
|
releaseLock = await acquireProjectLock(projectRoot);
|
|
5832
|
-
if (!validProviders.includes(
|
|
5846
|
+
if (!validProviders.includes(provider)) {
|
|
5833
5847
|
spinner.fail("Invalid provider");
|
|
5834
5848
|
console.error(chalk10.red(`
|
|
5835
5849
|
\u274C Invalid provider: ${options.provider}`));
|
|
@@ -5871,7 +5885,7 @@ async function chatCommand(message, options) {
|
|
|
5871
5885
|
const { generateSharedComponent: generateSharedComponent6 } = await import("@getcoherent/core");
|
|
5872
5886
|
const { autoFixCode: autoFixCode2 } = await import("./quality-validator-IM6YFKLI.js");
|
|
5873
5887
|
const { extractPropsInterface, extractDependencies } = await import("./component-extractor-VYJLT5NR.js");
|
|
5874
|
-
const aiProvider = await createAIProvider2(
|
|
5888
|
+
const aiProvider = await createAIProvider2(provider ?? "auto");
|
|
5875
5889
|
const prompt = `Generate a React component called "${componentName}". Description: ${message}.
|
|
5876
5890
|
Use shadcn/ui components and Tailwind CSS semantic tokens. Export the component as a named export.
|
|
5877
5891
|
Include a TypeScript props interface.
|
|
@@ -6002,7 +6016,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6002
6016
|
) || []).length >= SPLIT_THRESHOLD);
|
|
6003
6017
|
if (multiPageHint) {
|
|
6004
6018
|
try {
|
|
6005
|
-
const splitResult = await splitGeneratePages(spinner, message, modCtx,
|
|
6019
|
+
const splitResult = await splitGeneratePages(spinner, message, modCtx, provider, parseOpts);
|
|
6006
6020
|
requests = splitResult.requests;
|
|
6007
6021
|
if (splitResult.plan && projectRoot) {
|
|
6008
6022
|
savePlan(projectRoot, splitResult.plan);
|
|
@@ -6012,7 +6026,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6012
6026
|
} catch {
|
|
6013
6027
|
spinner.warn("Split generation encountered an issue \u2014 trying page-by-page...");
|
|
6014
6028
|
try {
|
|
6015
|
-
const planResult = await parseModification(message, modCtx,
|
|
6029
|
+
const planResult = await parseModification(message, modCtx, provider, { ...parseOpts, planOnly: true });
|
|
6016
6030
|
const pageReqs = planResult.requests.filter((r) => r.type === "add-page");
|
|
6017
6031
|
requests = [];
|
|
6018
6032
|
for (let i = 0; i < pageReqs.length; i++) {
|
|
@@ -6024,7 +6038,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6024
6038
|
const single = await parseModification(
|
|
6025
6039
|
`Create ONE page called "${pageName}" at route "${pageRoute}". Context: ${message}. Generate complete pageCode for this single page only.`,
|
|
6026
6040
|
modCtx,
|
|
6027
|
-
|
|
6041
|
+
provider,
|
|
6028
6042
|
parseOpts
|
|
6029
6043
|
);
|
|
6030
6044
|
const codePage = single.requests.find((r) => r.type === "add-page");
|
|
@@ -6062,7 +6076,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6062
6076
|
} catch {
|
|
6063
6077
|
}
|
|
6064
6078
|
try {
|
|
6065
|
-
const result = await parseModification(message, modCtx,
|
|
6079
|
+
const result = await parseModification(message, modCtx, provider, { ...parseOpts, reusePlanDirective });
|
|
6066
6080
|
requests = result.requests;
|
|
6067
6081
|
uxRecommendations = result.uxRecommendations;
|
|
6068
6082
|
const pagesWithoutCode = requests.filter(
|
|
@@ -6078,7 +6092,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6078
6092
|
const single = await parseModification(
|
|
6079
6093
|
`Create a page called "${pageName}" at route "${page.route || "/" + (page.id || pageName.toLowerCase())}". ${message}. Generate complete pageCode for this ONE page only.`,
|
|
6080
6094
|
modCtx,
|
|
6081
|
-
|
|
6095
|
+
provider,
|
|
6082
6096
|
parseOpts
|
|
6083
6097
|
);
|
|
6084
6098
|
const codePage = single.requests.find((r) => r.type === "add-page");
|
|
@@ -6096,7 +6110,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6096
6110
|
if (isTruncated || isJsonError) {
|
|
6097
6111
|
spinner.warn("Response too large \u2014 splitting into smaller requests...");
|
|
6098
6112
|
try {
|
|
6099
|
-
const splitResult = await splitGeneratePages(spinner, message, modCtx,
|
|
6113
|
+
const splitResult = await splitGeneratePages(spinner, message, modCtx, provider, parseOpts);
|
|
6100
6114
|
requests = splitResult.requests;
|
|
6101
6115
|
if (splitResult.plan && projectRoot) {
|
|
6102
6116
|
savePlan(projectRoot, splitResult.plan);
|
|
@@ -6230,15 +6244,15 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6230
6244
|
if (missingComponents.length > 0) {
|
|
6231
6245
|
spinner.stop();
|
|
6232
6246
|
console.log(chalk10.cyan("\n\u{1F50D} Pre-flight check: Installing missing components...\n"));
|
|
6233
|
-
const
|
|
6247
|
+
const provider2 = getComponentProvider();
|
|
6234
6248
|
for (const componentId of missingComponents) {
|
|
6235
6249
|
if (DEBUG4) {
|
|
6236
6250
|
console.log(chalk10.gray(` [DEBUG] Trying to install: ${componentId}`));
|
|
6237
|
-
console.log(chalk10.gray(` [DEBUG] provider.has(${componentId}): ${
|
|
6251
|
+
console.log(chalk10.gray(` [DEBUG] provider.has(${componentId}): ${provider2.has(componentId)}`));
|
|
6238
6252
|
}
|
|
6239
|
-
if (
|
|
6253
|
+
if (provider2.has(componentId)) {
|
|
6240
6254
|
try {
|
|
6241
|
-
const result = await
|
|
6255
|
+
const result = await provider2.installComponent(componentId, projectRoot);
|
|
6242
6256
|
if (DEBUG4) console.log(chalk10.gray(` [DEBUG] installComponent result: ${result.success}`));
|
|
6243
6257
|
if (result.success && result.componentDef) {
|
|
6244
6258
|
if (!cm.read(componentId)) {
|
|
@@ -6323,7 +6337,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6323
6337
|
spinner.start("Applying modifications...");
|
|
6324
6338
|
const results = [];
|
|
6325
6339
|
for (const request of normalizedRequests) {
|
|
6326
|
-
const result = await applyModification(request, dsm, cm, pm, projectRoot,
|
|
6340
|
+
const result = await applyModification(request, dsm, cm, pm, projectRoot, provider, message);
|
|
6327
6341
|
results.push(result);
|
|
6328
6342
|
}
|
|
6329
6343
|
for (const request of normalizedRequests) {
|
|
@@ -6339,7 +6353,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6339
6353
|
}
|
|
6340
6354
|
try {
|
|
6341
6355
|
const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
|
|
6342
|
-
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-
|
|
6356
|
+
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-PFCUSBMG.js");
|
|
6343
6357
|
const manifest2 = await loadManifest6(projectRoot);
|
|
6344
6358
|
const reuseplan = projectRoot ? loadPlan(projectRoot) : null;
|
|
6345
6359
|
if (manifest2.shared.length > 0) {
|
|
@@ -6414,7 +6428,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6414
6428
|
const { requests: linkedRequests } = await parseModification(
|
|
6415
6429
|
`add ${pageName} page at route ${linkedRoute}`,
|
|
6416
6430
|
{ config: dsm.getConfig(), componentManager: cm },
|
|
6417
|
-
|
|
6431
|
+
provider
|
|
6418
6432
|
);
|
|
6419
6433
|
let anySuccess = false;
|
|
6420
6434
|
for (const raw of linkedRequests.map((r) => applyDefaults(r))) {
|
|
@@ -6423,7 +6437,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
|
|
|
6423
6437
|
scaffoldSpinner.warn(` Skipped scaffold: ${linkedReq.error}`);
|
|
6424
6438
|
continue;
|
|
6425
6439
|
}
|
|
6426
|
-
const linkedResult = await applyModification(linkedReq, dsm, cm, pm, projectRoot,
|
|
6440
|
+
const linkedResult = await applyModification(linkedReq, dsm, cm, pm, projectRoot, provider);
|
|
6427
6441
|
if (linkedResult.success) {
|
|
6428
6442
|
results.push(linkedResult);
|
|
6429
6443
|
normalizedRequests.push(linkedReq);
|
|
@@ -6711,7 +6725,7 @@ ${uxRecommendations}
|
|
|
6711
6725
|
console.log(chalk10.white(' coherent chat "add account page"'));
|
|
6712
6726
|
console.log(chalk10.white(' coherent chat "add settings page"'));
|
|
6713
6727
|
} else if (error.message.includes("API key not found") || error.message.includes("ANTHROPIC_API_KEY") || error.message.includes("OPENAI_API_KEY")) {
|
|
6714
|
-
const isOpenAI = error.message.includes("OpenAI") || typeof
|
|
6728
|
+
const isOpenAI = error.message.includes("OpenAI") || typeof provider !== "undefined" && provider === "openai";
|
|
6715
6729
|
const providerName = isOpenAI ? "OpenAI" : "Anthropic Claude";
|
|
6716
6730
|
const envVar = isOpenAI ? "OPENAI_API_KEY" : "ANTHROPIC_API_KEY";
|
|
6717
6731
|
const url = isOpenAI ? "https://platform.openai.com" : "https://console.anthropic.com";
|
|
@@ -7382,13 +7396,13 @@ async function fixMissingComponentExports(projectRoot) {
|
|
|
7382
7396
|
} catch {
|
|
7383
7397
|
}
|
|
7384
7398
|
const generator = new ComponentGenerator2(config2 || { components: [], pages: [], tokens: {} });
|
|
7385
|
-
const
|
|
7399
|
+
const provider = getComponentProvider();
|
|
7386
7400
|
for (const [componentId, needed] of neededExports) {
|
|
7387
7401
|
const componentFile = join9(uiDir, `${componentId}.tsx`);
|
|
7388
7402
|
if (!existsSync11(componentFile)) {
|
|
7389
|
-
if (
|
|
7403
|
+
if (provider.has(componentId)) {
|
|
7390
7404
|
try {
|
|
7391
|
-
const result = await
|
|
7405
|
+
const result = await provider.installComponent(componentId, projectRoot);
|
|
7392
7406
|
if (result.success) {
|
|
7393
7407
|
console.log(chalk11.dim(` \u2714 Installed missing ${componentId}.tsx`));
|
|
7394
7408
|
}
|
|
@@ -7421,9 +7435,9 @@ async function fixMissingComponentExports(projectRoot) {
|
|
|
7421
7435
|
}
|
|
7422
7436
|
const missing = [...needed].filter((n) => !existingExports.has(n));
|
|
7423
7437
|
if (missing.length === 0) continue;
|
|
7424
|
-
if (
|
|
7438
|
+
if (provider.has(componentId)) {
|
|
7425
7439
|
try {
|
|
7426
|
-
const result = await
|
|
7440
|
+
const result = await provider.installComponent(componentId, projectRoot, { force: true });
|
|
7427
7441
|
if (result.success) {
|
|
7428
7442
|
console.log(chalk11.dim(` \u2714 Reinstalled ${componentId}.tsx (added missing exports: ${missing.join(", ")})`));
|
|
7429
7443
|
}
|
|
@@ -7520,8 +7534,8 @@ function extractShadcnComponentFromModuleNotFound(msg) {
|
|
|
7520
7534
|
return m?.[1] ?? null;
|
|
7521
7535
|
}
|
|
7522
7536
|
async function autoInstallShadcnComponent(componentId, projectRoot) {
|
|
7523
|
-
const
|
|
7524
|
-
const result = await
|
|
7537
|
+
const provider = getComponentProvider();
|
|
7538
|
+
const result = await provider.installComponent(componentId, projectRoot);
|
|
7525
7539
|
return result.success;
|
|
7526
7540
|
}
|
|
7527
7541
|
var DEFAULT_PORT = 3e3;
|
|
@@ -8310,8 +8324,8 @@ async function fixCommand(opts = {}) {
|
|
|
8310
8324
|
if (!existsSync13(filePath)) missingFiles.push(id);
|
|
8311
8325
|
}
|
|
8312
8326
|
}
|
|
8313
|
-
const
|
|
8314
|
-
const toInstall = [.../* @__PURE__ */ new Set([...missingComponents, ...missingFiles])].filter((id) =>
|
|
8327
|
+
const provider = getComponentProvider();
|
|
8328
|
+
const toInstall = [.../* @__PURE__ */ new Set([...missingComponents, ...missingFiles])].filter((id) => provider.has(id));
|
|
8315
8329
|
if (toInstall.length > 0) {
|
|
8316
8330
|
if (dryRun) {
|
|
8317
8331
|
fixes.push(`Would install components: ${toInstall.join(", ")}`);
|
|
@@ -8320,7 +8334,7 @@ async function fixCommand(opts = {}) {
|
|
|
8320
8334
|
let installed = 0;
|
|
8321
8335
|
for (const componentId of toInstall) {
|
|
8322
8336
|
try {
|
|
8323
|
-
const result = await
|
|
8337
|
+
const result = await provider.installComponent(componentId, projectRoot);
|
|
8324
8338
|
if (!result.success) continue;
|
|
8325
8339
|
if (result.componentDef && !cm.read(componentId)) {
|
|
8326
8340
|
const regResult = await cm.register(result.componentDef);
|
|
@@ -8479,8 +8493,8 @@ async function fixCommand(opts = {}) {
|
|
|
8479
8493
|
console.log(chalk15.green(` \u2714 ${verb} syntax: ${syntaxFixed} file(s) (use client, metadata, quotes)`));
|
|
8480
8494
|
}
|
|
8481
8495
|
try {
|
|
8482
|
-
const { loadPlan: loadPlan2 } = await import("./plan-generator-
|
|
8483
|
-
const { ensurePlanGroupLayouts: ensurePlanGroupLayouts2 } = await import("./code-generator-
|
|
8496
|
+
const { loadPlan: loadPlan2 } = await import("./plan-generator-A3YN473Q.js");
|
|
8497
|
+
const { ensurePlanGroupLayouts: ensurePlanGroupLayouts2 } = await import("./code-generator-SKXX6PQG.js");
|
|
8484
8498
|
const plan = loadPlan2(projectRoot);
|
|
8485
8499
|
if (plan) {
|
|
8486
8500
|
if (!dsm) {
|
|
@@ -8495,9 +8509,10 @@ async function fixCommand(opts = {}) {
|
|
|
8495
8509
|
const sidebarPath = resolve8(projectRoot, "components", "shared", "sidebar.tsx");
|
|
8496
8510
|
if (hasSidebar && !existsSync13(sidebarPath) && !dryRun) {
|
|
8497
8511
|
const sidebarUiPath = resolve8(projectRoot, "components", "ui", "sidebar.tsx");
|
|
8498
|
-
|
|
8512
|
+
const sidebarProvider = getComponentProvider();
|
|
8513
|
+
if (!existsSync13(sidebarUiPath) && sidebarProvider.has("sidebar")) {
|
|
8499
8514
|
try {
|
|
8500
|
-
await
|
|
8515
|
+
await sidebarProvider.installComponent("sidebar", projectRoot);
|
|
8501
8516
|
console.log(chalk15.green(" \u2714 Auto-installed Sidebar UI component"));
|
|
8502
8517
|
} catch {
|
|
8503
8518
|
console.log(chalk15.yellow(" \u26A0 Could not install Sidebar UI component"));
|
|
@@ -8543,7 +8558,7 @@ async function fixCommand(opts = {}) {
|
|
|
8543
8558
|
const publicExists = existsSync13(publicLayoutPath);
|
|
8544
8559
|
const needsPublicLayout = !publicExists || !readFileSync10(publicLayoutPath, "utf-8").includes("<Header");
|
|
8545
8560
|
if (needsPublicLayout) {
|
|
8546
|
-
const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-
|
|
8561
|
+
const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-SKXX6PQG.js");
|
|
8547
8562
|
mkdirSync7(resolve8(projectRoot, "app", "(public)"), { recursive: true });
|
|
8548
8563
|
const publicResult = safeWrite(publicLayoutPath, buildPublicLayoutCodeForSidebar(), projectRoot, backups);
|
|
8549
8564
|
if (publicResult.ok) {
|
|
@@ -8592,7 +8607,7 @@ async function fixCommand(opts = {}) {
|
|
|
8592
8607
|
}
|
|
8593
8608
|
const themeTogglePath = resolve8(projectRoot, "components", "shared", "theme-toggle.tsx");
|
|
8594
8609
|
if (!existsSync13(themeTogglePath)) {
|
|
8595
|
-
const { generateThemeToggleCode } = await import("./code-generator-
|
|
8610
|
+
const { generateThemeToggleCode } = await import("./code-generator-SKXX6PQG.js");
|
|
8596
8611
|
mkdirSync7(resolve8(projectRoot, "components", "shared"), { recursive: true });
|
|
8597
8612
|
const themeResult = safeWrite(themeTogglePath, generateThemeToggleCode(), projectRoot, backups);
|
|
8598
8613
|
if (themeResult.ok) {
|
|
@@ -8613,7 +8628,7 @@ async function fixCommand(opts = {}) {
|
|
|
8613
8628
|
const isMinimal = appLayoutCode.length < 500 && !appLayoutCode.includes("Header") && !appLayoutCode.includes("Footer") && !appLayoutCode.includes("Sidebar") && !appLayoutCode.includes("SidebarProvider") && !appLayoutCode.includes("SidebarTrigger") && !appLayoutCode.includes("Sheet");
|
|
8614
8629
|
const navType = dsm.getConfig().navigation?.type || "header";
|
|
8615
8630
|
if (isMinimal && navType !== "none") {
|
|
8616
|
-
const { buildAppLayoutCode, buildGroupLayoutCode } = await import("./code-generator-
|
|
8631
|
+
const { buildAppLayoutCode, buildGroupLayoutCode } = await import("./code-generator-SKXX6PQG.js");
|
|
8617
8632
|
const isSidebar = navType === "sidebar" || navType === "both";
|
|
8618
8633
|
const newLayout = isSidebar ? buildAppLayoutCode(navType, dsm.getConfig().name) : buildGroupLayoutCode("header", dsm.getConfig().pages?.map((p) => p.name) || [], dsm.getConfig().name);
|
|
8619
8634
|
if (!dryRun) {
|
|
@@ -9160,7 +9175,7 @@ async function checkCommand(opts = {}) {
|
|
|
9160
9175
|
if (!skipShared) {
|
|
9161
9176
|
try {
|
|
9162
9177
|
const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
|
|
9163
|
-
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-
|
|
9178
|
+
const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-PFCUSBMG.js");
|
|
9164
9179
|
const manifest = await loadManifest9(projectRoot);
|
|
9165
9180
|
const appDir = resolve9(projectRoot, "app");
|
|
9166
9181
|
const pageFiles = existsSync14(appDir) ? findTsxFiles(appDir) : [];
|
|
@@ -10655,8 +10670,8 @@ async function migrateAction(options) {
|
|
|
10655
10670
|
console.log(chalk28.yellow("No components/ui directory found. Nothing to migrate."));
|
|
10656
10671
|
return;
|
|
10657
10672
|
}
|
|
10658
|
-
const
|
|
10659
|
-
const managedIds = new Set(
|
|
10673
|
+
const provider = getComponentProvider();
|
|
10674
|
+
const managedIds = new Set(provider.listNames());
|
|
10660
10675
|
const files = readdirSync9(uiDir).filter((f) => f.endsWith(".tsx"));
|
|
10661
10676
|
const migratable = files.map((f) => f.replace(".tsx", "")).filter((id) => managedIds.has(id));
|
|
10662
10677
|
if (migratable.length === 0) {
|
|
@@ -10680,7 +10695,7 @@ Found ${migratable.length} component(s) to migrate:`));
|
|
|
10680
10695
|
const filePath = join16(uiDir, `${id}.tsx`);
|
|
10681
10696
|
if (existsSync19(filePath)) rmSync6(filePath);
|
|
10682
10697
|
}
|
|
10683
|
-
const results = await
|
|
10698
|
+
const results = await provider.installBatch(migratable, projectRoot, { force: true });
|
|
10684
10699
|
let migrated = 0;
|
|
10685
10700
|
for (const [id, result] of results) {
|
|
10686
10701
|
if (result.success) {
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
routeToKey,
|
|
12
12
|
savePlan,
|
|
13
13
|
updateArchitecturePlan
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-BNHIEEXH.js";
|
|
15
|
+
import "./chunk-PVVL26FX.js";
|
|
16
16
|
import "./chunk-U5SNPHVU.js";
|
|
17
17
|
import "./chunk-3RG5ZIWI.js";
|
|
18
18
|
export {
|