@contentful/experience-design-system-cli 2.34.5-dev-build-131193c7.0 → 2.34.5-dev-build-a95aeeba.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/package.json
CHANGED
|
@@ -11,6 +11,8 @@ export declare function buildGenerateComponentsArgs(opts: {
|
|
|
11
11
|
generatePromptPath?: string;
|
|
12
12
|
promptOverrides?: string[];
|
|
13
13
|
existingEntitiesPath?: string;
|
|
14
|
+
restoreCache?: boolean;
|
|
15
|
+
cachedComponents?: string[];
|
|
14
16
|
}): string[];
|
|
15
17
|
export declare function buildGenerateTokensArgs(opts: {
|
|
16
18
|
rawTokensPath: string;
|
package/dist/src/index.js
CHANGED
|
@@ -110,11 +110,15 @@ var init_credentials_store = __esm({
|
|
|
110
110
|
var render_with_goodbye_exports = {};
|
|
111
111
|
__export(render_with_goodbye_exports, {
|
|
112
112
|
GoodbyeBoundary: () => GoodbyeBoundary,
|
|
113
|
-
renderWithGoodbye: () => renderWithGoodbye
|
|
113
|
+
renderWithGoodbye: () => renderWithGoodbye,
|
|
114
|
+
useScreenTransitionClear: () => useScreenTransitionClear
|
|
114
115
|
});
|
|
115
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
116
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
116
117
|
import { render, Text, useInput } from "ink";
|
|
117
118
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
119
|
+
function useScreenTransitionClear() {
|
|
120
|
+
return useContext(ScreenTransitionClearContext);
|
|
121
|
+
}
|
|
118
122
|
function GoodbyeBoundary({ children }) {
|
|
119
123
|
const [isExiting, setIsExiting] = useState(false);
|
|
120
124
|
const isExitingRef = useRef(false);
|
|
@@ -138,16 +142,26 @@ function GoodbyeBoundary({ children }) {
|
|
|
138
142
|
return isExiting ? /* @__PURE__ */ jsx(Text, { children: "Goodbye!" }) : /* @__PURE__ */ jsx(Fragment, { children });
|
|
139
143
|
}
|
|
140
144
|
function renderWithGoodbye(element, options) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
+
const instanceRef = {};
|
|
146
|
+
const clearScreen = () => {
|
|
147
|
+
instanceRef.current?.clear();
|
|
148
|
+
};
|
|
149
|
+
const instance = render(
|
|
150
|
+
/* @__PURE__ */ jsx(ScreenTransitionClearContext.Provider, { value: clearScreen, children: /* @__PURE__ */ jsx(GoodbyeBoundary, { children: element }) }),
|
|
151
|
+
{
|
|
152
|
+
...options,
|
|
153
|
+
exitOnCtrlC: false
|
|
154
|
+
}
|
|
155
|
+
);
|
|
156
|
+
instanceRef.current = instance;
|
|
157
|
+
return instance;
|
|
145
158
|
}
|
|
146
|
-
var GOODBYE_RENDER_DELAY_MS;
|
|
159
|
+
var GOODBYE_RENDER_DELAY_MS, ScreenTransitionClearContext;
|
|
147
160
|
var init_render_with_goodbye = __esm({
|
|
148
161
|
"packages/experience-design-system-cli/src/tui/render-with-goodbye.tsx"() {
|
|
149
162
|
"use strict";
|
|
150
163
|
GOODBYE_RENDER_DELAY_MS = 50;
|
|
164
|
+
ScreenTransitionClearContext = createContext(() => void 0);
|
|
151
165
|
}
|
|
152
166
|
});
|
|
153
167
|
|
|
@@ -1955,8 +1969,7 @@ function hashComponentShape(component) {
|
|
|
1955
1969
|
})),
|
|
1956
1970
|
slots: component.slots.map((s) => ({
|
|
1957
1971
|
name: s.name,
|
|
1958
|
-
isDefault: s.isDefault
|
|
1959
|
-
allowedComponents: [...s.allowedComponents ?? []].sort()
|
|
1972
|
+
isDefault: s.isDefault
|
|
1960
1973
|
}))
|
|
1961
1974
|
};
|
|
1962
1975
|
return createHash2("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
@@ -3546,15 +3559,38 @@ function lookupCacheByEntity(db, entityType, entityId) {
|
|
|
3546
3559
|
};
|
|
3547
3560
|
}
|
|
3548
3561
|
function storeCache(db, inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash = "") {
|
|
3562
|
+
storeCaches(db, [{ inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash }]);
|
|
3563
|
+
}
|
|
3564
|
+
function storeCaches(db, entries) {
|
|
3565
|
+
if (entries.length === 0) return;
|
|
3549
3566
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3550
|
-
db.prepare(
|
|
3567
|
+
const insert = db.prepare(
|
|
3551
3568
|
`INSERT INTO generation_cache (input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
3552
3569
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3553
3570
|
ON CONFLICT(input_hash, prompt_hash, entity_type, entity_id) DO UPDATE SET
|
|
3554
3571
|
source_session_id = excluded.source_session_id,
|
|
3555
3572
|
human_edited = CASE WHEN generation_cache.human_edited = 1 THEN 1 ELSE excluded.human_edited END,
|
|
3556
3573
|
updated_at = excluded.updated_at`
|
|
3557
|
-
)
|
|
3574
|
+
);
|
|
3575
|
+
db.exec("BEGIN");
|
|
3576
|
+
try {
|
|
3577
|
+
for (const entry of entries) {
|
|
3578
|
+
insert.run(
|
|
3579
|
+
entry.inputHash,
|
|
3580
|
+
entry.entityType,
|
|
3581
|
+
entry.entityId,
|
|
3582
|
+
entry.sourceSessionId,
|
|
3583
|
+
entry.humanEdited ? 1 : 0,
|
|
3584
|
+
now,
|
|
3585
|
+
now,
|
|
3586
|
+
entry.promptHash ?? ""
|
|
3587
|
+
);
|
|
3588
|
+
}
|
|
3589
|
+
db.exec("COMMIT");
|
|
3590
|
+
} catch (e) {
|
|
3591
|
+
db.exec("ROLLBACK");
|
|
3592
|
+
throw e;
|
|
3593
|
+
}
|
|
3558
3594
|
}
|
|
3559
3595
|
function storeScannedFiles(db, sessionId2, filePaths) {
|
|
3560
3596
|
db.exec("BEGIN");
|
|
@@ -3604,9 +3640,9 @@ function loadSlotCycles(db, sessionId2) {
|
|
|
3604
3640
|
suggestedBreak: r.suggested_break_json ? JSON.parse(r.suggested_break_json) : null
|
|
3605
3641
|
}));
|
|
3606
3642
|
}
|
|
3607
|
-
function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentId) {
|
|
3643
|
+
function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentId, manageTransaction = true) {
|
|
3608
3644
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3609
|
-
db.exec("BEGIN");
|
|
3645
|
+
if (manageTransaction) db.exec("BEGIN");
|
|
3610
3646
|
try {
|
|
3611
3647
|
const srcComp = db.prepare(
|
|
3612
3648
|
`SELECT description, status, component_description_rationale, props_rationale, slots_rationale
|
|
@@ -3682,6 +3718,19 @@ function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentI
|
|
|
3682
3718
|
insertSAC.run(targetSessionId, componentId, sac.slot_name, sac.allowed_component, sac.position);
|
|
3683
3719
|
}
|
|
3684
3720
|
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
3721
|
+
if (manageTransaction) db.exec("COMMIT");
|
|
3722
|
+
} catch (e) {
|
|
3723
|
+
if (manageTransaction) db.exec("ROLLBACK");
|
|
3724
|
+
throw e;
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
function copyComponentsFromCache(db, entries) {
|
|
3728
|
+
if (entries.length === 0) return;
|
|
3729
|
+
db.exec("BEGIN");
|
|
3730
|
+
try {
|
|
3731
|
+
for (const entry of entries) {
|
|
3732
|
+
copyComponentFromCache(db, entry.sourceSessionId, entry.targetSessionId, entry.componentId, false);
|
|
3733
|
+
}
|
|
3685
3734
|
db.exec("COMMIT");
|
|
3686
3735
|
} catch (e) {
|
|
3687
3736
|
db.exec("ROLLBACK");
|
|
@@ -4824,43 +4873,41 @@ function printFallbackInstructions(options) {
|
|
|
4824
4873
|
lines.push(` Re-run the generate command with the agent available, or use --dry-run to inspect the prompt.`);
|
|
4825
4874
|
process.stderr.write(lines.join("\n") + "\n");
|
|
4826
4875
|
}
|
|
4827
|
-
|
|
4876
|
+
function cachedComponentResult(componentName, warnings = []) {
|
|
4877
|
+
return {
|
|
4878
|
+
componentName,
|
|
4879
|
+
classified: 0,
|
|
4880
|
+
excluded: 0,
|
|
4881
|
+
slots: 0,
|
|
4882
|
+
warnings,
|
|
4883
|
+
failed: false,
|
|
4884
|
+
cached: true,
|
|
4885
|
+
renamedSlotsCount: 0
|
|
4886
|
+
};
|
|
4887
|
+
}
|
|
4888
|
+
function normalizeComponentForCache(component) {
|
|
4889
|
+
const slots = component.slots.map((slot, index, allSlots) => ({
|
|
4890
|
+
...slot,
|
|
4891
|
+
name: slot.name.trim() || (allSlots.length === 1 ? "children" : `slot_${index}`)
|
|
4892
|
+
}));
|
|
4893
|
+
return { ...component, slots };
|
|
4894
|
+
}
|
|
4895
|
+
function lookupComponentCache(db, component, promptHash) {
|
|
4896
|
+
const normalized = normalizeComponentForCache(component);
|
|
4897
|
+
const inputHash = hashComponentShape(normalized);
|
|
4898
|
+
const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
|
|
4899
|
+
if (cached) return cached;
|
|
4900
|
+
const legacyInputHash = hashComponentShape(component);
|
|
4901
|
+
return legacyInputHash === inputHash ? null : lookupCache(db, legacyInputHash, "component", component.component_id, promptHash);
|
|
4902
|
+
}
|
|
4903
|
+
function resolveComponentCache(db, component, promptHash) {
|
|
4904
|
+
const cached = lookupComponentCache(db, component, promptHash);
|
|
4905
|
+
if (cached) return { entry: cached, humanEdited: cached.humanEdited };
|
|
4906
|
+
const pinned = lookupCacheByEntity(db, "component", component.component_id);
|
|
4907
|
+
return pinned?.humanEdited ? { entry: pinned, humanEdited: true } : null;
|
|
4908
|
+
}
|
|
4909
|
+
async function runOneComponent(agent, model, db, sessionId2, component, tokensInline, tokenMapInline, index, total, verbose, noCache, skillPathOverride, skillContentOverride, promptHash, existingContentfulEntities, existingTokensInline, precomputedCachedNames) {
|
|
4828
4910
|
const pos = c.dim(`[${index + 1}/${total}]`);
|
|
4829
|
-
if (!noCache) {
|
|
4830
|
-
const inputHash = hashComponentShape(component);
|
|
4831
|
-
const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
|
|
4832
|
-
if (cached) {
|
|
4833
|
-
copyComponentFromCache(db, cached.sourceSessionId, sessionId2, component.component_id);
|
|
4834
|
-
process.stderr.write(` ${pos} ${c.bold(component.name)} ${c.green("cached")}
|
|
4835
|
-
`);
|
|
4836
|
-
return {
|
|
4837
|
-
componentName: component.name,
|
|
4838
|
-
classified: 0,
|
|
4839
|
-
excluded: 0,
|
|
4840
|
-
slots: 0,
|
|
4841
|
-
warnings: [],
|
|
4842
|
-
failed: false,
|
|
4843
|
-
cached: true,
|
|
4844
|
-
renamedSlotsCount: 0
|
|
4845
|
-
};
|
|
4846
|
-
}
|
|
4847
|
-
const pinned = lookupCacheByEntity(db, "component", component.component_id);
|
|
4848
|
-
if (pinned?.humanEdited) {
|
|
4849
|
-
copyComponentFromCache(db, pinned.sourceSessionId, sessionId2, component.component_id);
|
|
4850
|
-
process.stderr.write(` ${pos} ${c.bold(component.name)} ${c.cyan("pinned (human-edited)")}
|
|
4851
|
-
`);
|
|
4852
|
-
return {
|
|
4853
|
-
componentName: component.name,
|
|
4854
|
-
classified: 0,
|
|
4855
|
-
excluded: 0,
|
|
4856
|
-
slots: 0,
|
|
4857
|
-
warnings: [`${component.name}: source changed but human edits preserved`],
|
|
4858
|
-
failed: false,
|
|
4859
|
-
cached: true,
|
|
4860
|
-
renamedSlotsCount: 0
|
|
4861
|
-
};
|
|
4862
|
-
}
|
|
4863
|
-
}
|
|
4864
4911
|
const { renames, warnings: renameWarnings } = renameEmptySlots(
|
|
4865
4912
|
db,
|
|
4866
4913
|
sessionId2,
|
|
@@ -4875,6 +4922,37 @@ async function runOneComponent(agent, model, db, sessionId2, component, tokensIn
|
|
|
4875
4922
|
for (const w of renameWarnings) process.stderr.write(` ${c.yellow("\u26A0")} ${w}
|
|
4876
4923
|
`);
|
|
4877
4924
|
}
|
|
4925
|
+
const cacheComponent = normalizeComponentForCache(component);
|
|
4926
|
+
if (!noCache && precomputedCachedNames.has(component.name)) {
|
|
4927
|
+
process.stderr.write(` ${pos} ${c.bold(component.name)} ${c.green("cached")}
|
|
4928
|
+
`);
|
|
4929
|
+
return cachedComponentResult(component.name);
|
|
4930
|
+
}
|
|
4931
|
+
if (!noCache) {
|
|
4932
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
4933
|
+
const resolution = resolveComponentCache(db, component, promptHash);
|
|
4934
|
+
if (resolution && !resolution.humanEdited) {
|
|
4935
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id);
|
|
4936
|
+
storeCache(
|
|
4937
|
+
db,
|
|
4938
|
+
inputHash,
|
|
4939
|
+
"component",
|
|
4940
|
+
component.component_id,
|
|
4941
|
+
resolution.entry.sourceSessionId,
|
|
4942
|
+
resolution.entry.humanEdited,
|
|
4943
|
+
promptHash
|
|
4944
|
+
);
|
|
4945
|
+
process.stderr.write(` ${pos} ${c.bold(component.name)} ${c.green("cached")}
|
|
4946
|
+
`);
|
|
4947
|
+
return cachedComponentResult(component.name);
|
|
4948
|
+
}
|
|
4949
|
+
if (resolution?.humanEdited) {
|
|
4950
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id);
|
|
4951
|
+
process.stderr.write(` ${pos} ${c.bold(component.name)} ${c.cyan("pinned (human-edited)")}
|
|
4952
|
+
`);
|
|
4953
|
+
return cachedComponentResult(component.name, [`${component.name}: source changed but human edits preserved`]);
|
|
4954
|
+
}
|
|
4955
|
+
}
|
|
4878
4956
|
const rawComponentsInline = JSON.stringify(
|
|
4879
4957
|
[
|
|
4880
4958
|
{
|
|
@@ -4944,7 +5022,7 @@ ${outputBuf}`);
|
|
|
4944
5022
|
}
|
|
4945
5023
|
const applied = applyToolCalls(db, sessionId2, component.component_id, component.name, calls, warnings);
|
|
4946
5024
|
if (!noCache) {
|
|
4947
|
-
const inputHash = hashComponentShape(
|
|
5025
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
4948
5026
|
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
4949
5027
|
}
|
|
4950
5028
|
return {
|
|
@@ -4968,7 +5046,7 @@ ${outputBuf}`);
|
|
|
4968
5046
|
renamedSlotsCount: renames.length
|
|
4969
5047
|
};
|
|
4970
5048
|
}
|
|
4971
|
-
async function runAllComponents(agent, model, db, sessionId2, components, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, skillContentOverride, promptHash, existingContentfulEntities, existingTokensInline) {
|
|
5049
|
+
async function runAllComponents(agent, model, db, sessionId2, components, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, skillContentOverride, promptHash, existingContentfulEntities, existingTokensInline, precomputedCachedNames) {
|
|
4972
5050
|
const concurrency = Number(process.env.EDS_GENERATE_CONCURRENCY ?? DEFAULT_COMPONENT_CONCURRENCY);
|
|
4973
5051
|
process.stderr.write(
|
|
4974
5052
|
`Categorizing ${c.bold(String(components.length))} component${components.length === 1 ? "" : "s"}` + c.dim(` (concurrency: ${concurrency})`) + "\n"
|
|
@@ -4995,7 +5073,8 @@ async function runAllComponents(agent, model, db, sessionId2, components, tokens
|
|
|
4995
5073
|
skillContentOverride,
|
|
4996
5074
|
promptHash,
|
|
4997
5075
|
existingContentfulEntities,
|
|
4998
|
-
existingTokensInline
|
|
5076
|
+
existingTokensInline,
|
|
5077
|
+
precomputedCachedNames
|
|
4999
5078
|
);
|
|
5000
5079
|
completed += 1;
|
|
5001
5080
|
process.stderr.write(`${formatGenerateProgressLine(completed, components.length, results[i].componentName)}
|
|
@@ -5024,6 +5103,15 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
5024
5103
|
return null;
|
|
5025
5104
|
}
|
|
5026
5105
|
}
|
|
5106
|
+
function parsePrecomputedCachedNames(value) {
|
|
5107
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
5108
|
+
try {
|
|
5109
|
+
const parsed = JSON.parse(value);
|
|
5110
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((name) => typeof name === "string") : []);
|
|
5111
|
+
} catch {
|
|
5112
|
+
return /* @__PURE__ */ new Set();
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5027
5115
|
async function runGenerateSkill(skill, opts, verbose = false) {
|
|
5028
5116
|
const savedCreds = await readExperiencesCredentials();
|
|
5029
5117
|
const agentName = opts.agent ?? savedCreds.agent;
|
|
@@ -5178,6 +5266,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5178
5266
|
if (skill === "components" && allComponents && sessionId2) {
|
|
5179
5267
|
const db = openPipelineDb();
|
|
5180
5268
|
let componentResults;
|
|
5269
|
+
const precomputedCachedNames = parsePrecomputedCachedNames(opts.cachedComponents);
|
|
5181
5270
|
try {
|
|
5182
5271
|
const existingContentfulEntitiesHashInputs = [];
|
|
5183
5272
|
if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
|
|
@@ -5189,6 +5278,52 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5189
5278
|
existingContentfulEntitiesHashInputs,
|
|
5190
5279
|
generatePrompt
|
|
5191
5280
|
);
|
|
5281
|
+
if (opts.cacheStatus) {
|
|
5282
|
+
const cacheEnabled = opts.cache !== false && process.env.EDS_NO_CACHE !== "1";
|
|
5283
|
+
const cachedComponents = cacheEnabled ? allComponents.flatMap((component) => {
|
|
5284
|
+
const resolution = resolveComponentCache(db, component, promptHash);
|
|
5285
|
+
return resolution ? [{ component, resolution }] : [];
|
|
5286
|
+
}) : [];
|
|
5287
|
+
if (cacheEnabled && opts.restoreCache) {
|
|
5288
|
+
const restorations = [];
|
|
5289
|
+
const rekeyed = [];
|
|
5290
|
+
const componentStatus = db.prepare(
|
|
5291
|
+
"SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?"
|
|
5292
|
+
);
|
|
5293
|
+
for (const { component, resolution } of cachedComponents) {
|
|
5294
|
+
const current = componentStatus.get(sessionId2, component.component_id);
|
|
5295
|
+
if (current?.status === "generated") continue;
|
|
5296
|
+
renameEmptySlots(db, sessionId2, component.component_id, component.name, component.slots.length);
|
|
5297
|
+
restorations.push({
|
|
5298
|
+
sourceSessionId: resolution.entry.sourceSessionId,
|
|
5299
|
+
targetSessionId: sessionId2,
|
|
5300
|
+
componentId: component.component_id
|
|
5301
|
+
});
|
|
5302
|
+
rekeyed.push({ component, cached: resolution.entry });
|
|
5303
|
+
}
|
|
5304
|
+
copyComponentsFromCache(db, restorations);
|
|
5305
|
+
storeCaches(
|
|
5306
|
+
db,
|
|
5307
|
+
rekeyed.map(({ component, cached }) => ({
|
|
5308
|
+
inputHash: hashComponentShape(normalizeComponentForCache(component)),
|
|
5309
|
+
entityType: "component",
|
|
5310
|
+
entityId: component.component_id,
|
|
5311
|
+
sourceSessionId: cached.sourceSessionId,
|
|
5312
|
+
humanEdited: cached.humanEdited,
|
|
5313
|
+
promptHash
|
|
5314
|
+
}))
|
|
5315
|
+
);
|
|
5316
|
+
}
|
|
5317
|
+
const fullyCached = cacheEnabled && cachedComponents.length === allComponents.length;
|
|
5318
|
+
process.stdout.write(`cache-status=${fullyCached ? "hit" : "miss"}
|
|
5319
|
+
`);
|
|
5320
|
+
process.stdout.write(
|
|
5321
|
+
`cache-components=${JSON.stringify(cachedComponents.map(({ component }) => component.name))}
|
|
5322
|
+
`
|
|
5323
|
+
);
|
|
5324
|
+
await exitWithAnalytics(0);
|
|
5325
|
+
return;
|
|
5326
|
+
}
|
|
5192
5327
|
componentResults = await runAllComponents(
|
|
5193
5328
|
agent,
|
|
5194
5329
|
model,
|
|
@@ -5203,7 +5338,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5203
5338
|
generatePrompt,
|
|
5204
5339
|
promptHash,
|
|
5205
5340
|
existingContentfulEntities,
|
|
5206
|
-
existingTokensInline
|
|
5341
|
+
existingTokensInline,
|
|
5342
|
+
precomputedCachedNames
|
|
5207
5343
|
);
|
|
5208
5344
|
} finally {
|
|
5209
5345
|
db.close();
|
|
@@ -5389,6 +5525,12 @@ function registerInternalGenerateCommand(program) {
|
|
|
5389
5525
|
"--existing-entities-path <path>",
|
|
5390
5526
|
"Path to the .existing-entities.json file written after CMA credentials are supplied. When present, per-component prompts include a summary of the target space so classifications can align to existing prop names/tokens. Missing/malformed files are treated as no-op."
|
|
5391
5527
|
);
|
|
5528
|
+
componentsCmd.option("--cache-status", "Check whether all selected component definitions are cached");
|
|
5529
|
+
componentsCmd.option("--restore-cache", "Restore cached component definitions into the current session");
|
|
5530
|
+
componentsCmd.option(
|
|
5531
|
+
"--cached-components <json>",
|
|
5532
|
+
"Component names already restored by a prior cache-status lookup; skip per-component cache lookup"
|
|
5533
|
+
);
|
|
5392
5534
|
addAgentFlags(componentsCmd).action(async (opts) => {
|
|
5393
5535
|
await runGenerateSkill("components", opts, opts.verbose ?? false);
|
|
5394
5536
|
});
|
|
@@ -26590,10 +26732,31 @@ var init_GenerateReviewStep = __esm({
|
|
|
26590
26732
|
|
|
26591
26733
|
// packages/experience-design-system-cli/src/import/tui/runScopeGate.ts
|
|
26592
26734
|
async function runScopeGate(opts) {
|
|
26735
|
+
const startedAt = Date.now();
|
|
26736
|
+
getDebugLogger().event("wizard", "scope-decision-persistence.start", {
|
|
26737
|
+
sessionId: opts.sessionId,
|
|
26738
|
+
acceptedCount: opts.decisions.accepted.length,
|
|
26739
|
+
rejectedCount: opts.decisions.rejected.length
|
|
26740
|
+
});
|
|
26593
26741
|
const db = openPipelineDb();
|
|
26594
26742
|
try {
|
|
26595
26743
|
applyScopeDecisions(db, opts.sessionId, opts.decisions);
|
|
26596
26744
|
await writeScopeDecisionsSnapshot(db, opts.sessionId, opts.decisions);
|
|
26745
|
+
getDebugLogger().event("wizard", "scope-decision-persistence.complete", {
|
|
26746
|
+
sessionId: opts.sessionId,
|
|
26747
|
+
acceptedCount: opts.decisions.accepted.length,
|
|
26748
|
+
rejectedCount: opts.decisions.rejected.length,
|
|
26749
|
+
durationMs: Date.now() - startedAt
|
|
26750
|
+
});
|
|
26751
|
+
} catch (error) {
|
|
26752
|
+
getDebugLogger().event("wizard", "scope-decision-persistence.error", {
|
|
26753
|
+
sessionId: opts.sessionId,
|
|
26754
|
+
acceptedCount: opts.decisions.accepted.length,
|
|
26755
|
+
rejectedCount: opts.decisions.rejected.length,
|
|
26756
|
+
durationMs: Date.now() - startedAt,
|
|
26757
|
+
error: error instanceof Error ? error.message : String(error)
|
|
26758
|
+
});
|
|
26759
|
+
throw error;
|
|
26597
26760
|
} finally {
|
|
26598
26761
|
db.close();
|
|
26599
26762
|
}
|
|
@@ -26607,6 +26770,7 @@ var init_runScopeGate = __esm({
|
|
|
26607
26770
|
"packages/experience-design-system-cli/src/import/tui/runScopeGate.ts"() {
|
|
26608
26771
|
"use strict";
|
|
26609
26772
|
init_persistence();
|
|
26773
|
+
init_debug_logger();
|
|
26610
26774
|
init_db();
|
|
26611
26775
|
}
|
|
26612
26776
|
});
|
|
@@ -26860,6 +27024,10 @@ function buildGenerateComponentsArgs(opts) {
|
|
|
26860
27024
|
if (opts.generatePromptPath) args.push("--generate-prompt-path", opts.generatePromptPath);
|
|
26861
27025
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
26862
27026
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
27027
|
+
if (opts.restoreCache) args.push("--restore-cache");
|
|
27028
|
+
if (opts.cachedComponents && opts.cachedComponents.length > 0) {
|
|
27029
|
+
args.push("--cached-components", JSON.stringify(opts.cachedComponents));
|
|
27030
|
+
}
|
|
26863
27031
|
return args;
|
|
26864
27032
|
}
|
|
26865
27033
|
function buildGenerateTokensArgs(opts) {
|
|
@@ -26943,6 +27111,17 @@ function logStep(entry) {
|
|
|
26943
27111
|
appendFileSync2(WIZARD_LOG, line);
|
|
26944
27112
|
getDebugLogger().event("wizard", "step", entry);
|
|
26945
27113
|
}
|
|
27114
|
+
function startWizardTimer(name, payload = {}) {
|
|
27115
|
+
const startedAt = Date.now();
|
|
27116
|
+
getDebugLogger().event("wizard", `${name}.start`, payload);
|
|
27117
|
+
return startedAt;
|
|
27118
|
+
}
|
|
27119
|
+
function finishWizardTimer(name, startedAt, payload = {}) {
|
|
27120
|
+
getDebugLogger().event("wizard", `${name}.complete`, {
|
|
27121
|
+
...payload,
|
|
27122
|
+
durationMs: Date.now() - startedAt
|
|
27123
|
+
});
|
|
27124
|
+
}
|
|
26946
27125
|
function WizardApp({
|
|
26947
27126
|
initialSpaceId = "",
|
|
26948
27127
|
initialEnvironmentId = "master",
|
|
@@ -26965,6 +27144,7 @@ function WizardApp({
|
|
|
26965
27144
|
const resolveWizardHost = (hostValue) => hostValue || defaultConfiguredHost;
|
|
26966
27145
|
const credentialKey = (spaceId, environmentId, cmaToken, hostValue) => [spaceId.trim(), environmentId.trim(), cmaToken.trim(), resolveWizardHost(hostValue)].join("\0");
|
|
26967
27146
|
const { columns: terminalWidth } = useTerminalSize();
|
|
27147
|
+
const clearScreenOnTransition = useScreenTransitionClear();
|
|
26968
27148
|
const logInit = useRef10(false);
|
|
26969
27149
|
const initialAgentAuthRef = useRef10(initialAgentAuth ?? null);
|
|
26970
27150
|
if (!logInit.current) {
|
|
@@ -26978,6 +27158,8 @@ function WizardApp({
|
|
|
26978
27158
|
});
|
|
26979
27159
|
const allowEmptyDeleteAllRef = useRef10(false);
|
|
26980
27160
|
const generateChildRef = useRef10(null);
|
|
27161
|
+
const generationCachePreflightRef = useRef10(null);
|
|
27162
|
+
const selectionToReviewStartedAtRef = useRef10(null);
|
|
26981
27163
|
const credentialsValidationIdRef = useRef10(0);
|
|
26982
27164
|
const pendingCredentialValidationRef = useRef10(null);
|
|
26983
27165
|
const validatedCredentialsKeyRef = useRef10(null);
|
|
@@ -26985,6 +27167,7 @@ function WizardApp({
|
|
|
26985
27167
|
const extractPromiseRef = useRef10(null);
|
|
26986
27168
|
const extractStartedRef = useRef10(false);
|
|
26987
27169
|
const credentialsReadyRef = useRef10(false);
|
|
27170
|
+
const agentAuthVerifiedRef = useRef10(false);
|
|
26988
27171
|
const scopeGateCompletedRef = useRef10(false);
|
|
26989
27172
|
const existingEntitiesPromiseRef = useRef10(null);
|
|
26990
27173
|
const generatePromiseRef = useRef10(null);
|
|
@@ -27055,7 +27238,10 @@ function WizardApp({
|
|
|
27055
27238
|
tokensPath: state.tokensPath
|
|
27056
27239
|
};
|
|
27057
27240
|
}, [state.extractSessionId, state.tokensPath]);
|
|
27058
|
-
const update = (partial) => {
|
|
27241
|
+
const update = (partial, options = {}) => {
|
|
27242
|
+
if (partial.step !== void 0 && partial.step !== state.step && options.clearScreen !== false) {
|
|
27243
|
+
clearScreenOnTransition();
|
|
27244
|
+
}
|
|
27059
27245
|
const sanitized = { ...partial };
|
|
27060
27246
|
if (sanitized.serverPreview) {
|
|
27061
27247
|
const p = sanitized.serverPreview;
|
|
@@ -27102,12 +27288,41 @@ function WizardApp({
|
|
|
27102
27288
|
logStep({ update: sanitized });
|
|
27103
27289
|
setState((prev) => ({ ...prev, ...partial }));
|
|
27104
27290
|
};
|
|
27105
|
-
const
|
|
27291
|
+
const finishSelectionToReviewTimer = (mode) => {
|
|
27292
|
+
const startedAt = selectionToReviewStartedAtRef.current;
|
|
27293
|
+
if (startedAt === null) return;
|
|
27294
|
+
selectionToReviewStartedAtRef.current = null;
|
|
27295
|
+
finishWizardTimer("selection-to-review", startedAt, { mode });
|
|
27296
|
+
};
|
|
27297
|
+
const runAgentAuthCheck = async (nextStep, deferStep = false) => {
|
|
27298
|
+
const timer = startWizardTimer("agent-auth-validation", {
|
|
27299
|
+
agent: state.agent,
|
|
27300
|
+
deferred: deferStep,
|
|
27301
|
+
nextStep
|
|
27302
|
+
});
|
|
27303
|
+
if (agentAuthVerifiedRef.current) {
|
|
27304
|
+
finishWizardTimer("agent-auth-validation", timer, { status: "already-verified" });
|
|
27305
|
+
if (!deferStep) update({ step: nextStep });
|
|
27306
|
+
return true;
|
|
27307
|
+
}
|
|
27106
27308
|
const authCheckStepNumber = state.tokensPath ? 4 : 3;
|
|
27107
27309
|
const prefetchedAuth = initialAgentAuthRef.current;
|
|
27108
27310
|
initialAgentAuthRef.current = null;
|
|
27109
|
-
if (!prefetchedAuth) update({ step: "checking-claude-auth", authCheckStepNumber });
|
|
27110
|
-
|
|
27311
|
+
if (!prefetchedAuth && !deferStep) update({ step: "checking-claude-auth", authCheckStepNumber });
|
|
27312
|
+
let status;
|
|
27313
|
+
try {
|
|
27314
|
+
status = await (prefetchedAuth ?? checkAgentAuth(state.agent));
|
|
27315
|
+
} catch (error) {
|
|
27316
|
+
finishWizardTimer("agent-auth-validation", timer, {
|
|
27317
|
+
status: "error",
|
|
27318
|
+
error: error instanceof Error ? error.message : String(error)
|
|
27319
|
+
});
|
|
27320
|
+
throw error;
|
|
27321
|
+
}
|
|
27322
|
+
finishWizardTimer("agent-auth-validation", timer, {
|
|
27323
|
+
status,
|
|
27324
|
+
prefetched: Boolean(prefetchedAuth)
|
|
27325
|
+
});
|
|
27111
27326
|
if (status === "not-found") {
|
|
27112
27327
|
update({
|
|
27113
27328
|
step: "error",
|
|
@@ -27131,7 +27346,8 @@ If you are using AWS Bedrock, run:
|
|
|
27131
27346
|
});
|
|
27132
27347
|
return false;
|
|
27133
27348
|
}
|
|
27134
|
-
|
|
27349
|
+
agentAuthVerifiedRef.current = true;
|
|
27350
|
+
if (!deferStep) update({ step: nextStep });
|
|
27135
27351
|
return true;
|
|
27136
27352
|
};
|
|
27137
27353
|
const runGenerateTokens = async (rawTokensPath, outDir, forceRegenerate = false) => {
|
|
@@ -27186,7 +27402,13 @@ If you are using AWS Bedrock, run:
|
|
|
27186
27402
|
update({ tokensPath, tokenSessionId, tokenCount, tokenGenerationStatus: "complete" });
|
|
27187
27403
|
return true;
|
|
27188
27404
|
};
|
|
27189
|
-
const runMapTokens2 = async (sessionId2) => {
|
|
27405
|
+
const runMapTokens2 = async (sessionId2, silent = false) => {
|
|
27406
|
+
const timer = startWizardTimer("token-mapping", {
|
|
27407
|
+
sessionId: sessionId2,
|
|
27408
|
+
silent,
|
|
27409
|
+
noCache: effectiveNoCache,
|
|
27410
|
+
skipAgent: skipMapTokens
|
|
27411
|
+
});
|
|
27190
27412
|
let mappablePropCount = 0;
|
|
27191
27413
|
let rawTokenCount = 0;
|
|
27192
27414
|
try {
|
|
@@ -27213,13 +27435,22 @@ If you are using AWS Bedrock, run:
|
|
|
27213
27435
|
errorStep: "map tokens",
|
|
27214
27436
|
errorMessage: error instanceof Error ? error.message : String(error)
|
|
27215
27437
|
});
|
|
27438
|
+
finishWizardTimer("token-mapping", timer, {
|
|
27439
|
+
status: "error",
|
|
27440
|
+
error: error instanceof Error ? error.message : String(error)
|
|
27441
|
+
});
|
|
27216
27442
|
return false;
|
|
27217
27443
|
}
|
|
27218
27444
|
if (!shouldRunMapTokens({ mappablePropCount, rawTokenCount })) {
|
|
27219
|
-
update({ mapTokensEligible: false, mapTokensStatus: "complete" });
|
|
27445
|
+
if (!silent) update({ mapTokensEligible: false, mapTokensStatus: "complete" });
|
|
27446
|
+
finishWizardTimer("token-mapping", timer, {
|
|
27447
|
+
status: "skipped",
|
|
27448
|
+
mappablePropCount,
|
|
27449
|
+
rawTokenCount
|
|
27450
|
+
});
|
|
27220
27451
|
return true;
|
|
27221
27452
|
}
|
|
27222
|
-
update({ mapTokensEligible: true, mapTokensStatus: "running" });
|
|
27453
|
+
if (!silent) update({ mapTokensEligible: true, mapTokensStatus: "running", step: "generating" });
|
|
27223
27454
|
const args = buildMapTokensArgs({
|
|
27224
27455
|
sessionId: sessionId2,
|
|
27225
27456
|
agent: state.agent,
|
|
@@ -27237,9 +27468,21 @@ If you are using AWS Bedrock, run:
|
|
|
27237
27468
|
errorStep: "map tokens",
|
|
27238
27469
|
errorMessage: result.stderr.trim() || "Unknown error"
|
|
27239
27470
|
});
|
|
27471
|
+
finishWizardTimer("token-mapping", timer, {
|
|
27472
|
+
status: "error",
|
|
27473
|
+
exitCode: result.exitCode,
|
|
27474
|
+
mappablePropCount,
|
|
27475
|
+
rawTokenCount
|
|
27476
|
+
});
|
|
27240
27477
|
return false;
|
|
27241
27478
|
}
|
|
27242
|
-
update({ mapTokensStatus: "complete" });
|
|
27479
|
+
if (!silent) update({ mapTokensStatus: "complete" });
|
|
27480
|
+
finishWizardTimer("token-mapping", timer, {
|
|
27481
|
+
status: "complete",
|
|
27482
|
+
exitCode: result.exitCode,
|
|
27483
|
+
mappablePropCount,
|
|
27484
|
+
rawTokenCount
|
|
27485
|
+
});
|
|
27243
27486
|
return true;
|
|
27244
27487
|
};
|
|
27245
27488
|
const startExistingEntitiesFetch = (projectPath, outDir) => {
|
|
@@ -27489,7 +27732,7 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
27489
27732
|
generateProgress: null
|
|
27490
27733
|
}));
|
|
27491
27734
|
};
|
|
27492
|
-
const
|
|
27735
|
+
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => ({
|
|
27493
27736
|
sessionId: extractSessionId,
|
|
27494
27737
|
tokensPath,
|
|
27495
27738
|
agent: state.agent,
|
|
@@ -27498,8 +27741,127 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
27498
27741
|
noCache: effectiveNoCache,
|
|
27499
27742
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {},
|
|
27500
27743
|
...generatePromptPath2 ? { generatePromptPath: generatePromptPath2 } : {},
|
|
27501
|
-
promptOverrides
|
|
27744
|
+
promptOverrides,
|
|
27745
|
+
...cachedComponents && cachedComponents.length > 0 ? { cachedComponents } : {}
|
|
27502
27746
|
});
|
|
27747
|
+
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents));
|
|
27748
|
+
const buildGenerateCliArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateComponentsArgs(
|
|
27749
|
+
buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents)
|
|
27750
|
+
);
|
|
27751
|
+
const checkGenerateCache = async (extractSessionId, tokensPath) => {
|
|
27752
|
+
const timer = startWizardTimer("generation-cache-status", {
|
|
27753
|
+
sessionId: extractSessionId,
|
|
27754
|
+
noCache: effectiveNoCache
|
|
27755
|
+
});
|
|
27756
|
+
if (effectiveNoCache) {
|
|
27757
|
+
finishWizardTimer("generation-cache-status", timer, { status: "skipped" });
|
|
27758
|
+
return false;
|
|
27759
|
+
}
|
|
27760
|
+
const result = await runCli([...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"]);
|
|
27761
|
+
const hit = result.exitCode === 0 && /^cache-status=hit$/m.test(result.stdout);
|
|
27762
|
+
finishWizardTimer("generation-cache-status", timer, {
|
|
27763
|
+
status: hit ? "hit" : "miss",
|
|
27764
|
+
exitCode: result.exitCode,
|
|
27765
|
+
...result.exitCode !== 0 ? { stderrTail: result.stderr.trim().slice(-500) } : {}
|
|
27766
|
+
});
|
|
27767
|
+
return hit;
|
|
27768
|
+
};
|
|
27769
|
+
const checkGenerateCacheComponents = async (extractSessionId, tokensPath, restoreCache = false) => {
|
|
27770
|
+
const timer = startWizardTimer("generation-cache-components", {
|
|
27771
|
+
sessionId: extractSessionId,
|
|
27772
|
+
restoreCache,
|
|
27773
|
+
noCache: effectiveNoCache
|
|
27774
|
+
});
|
|
27775
|
+
if (effectiveNoCache) {
|
|
27776
|
+
finishWizardTimer("generation-cache-components", timer, { status: "skipped" });
|
|
27777
|
+
return /* @__PURE__ */ new Set();
|
|
27778
|
+
}
|
|
27779
|
+
const args = [...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"];
|
|
27780
|
+
if (restoreCache) args.push("--restore-cache");
|
|
27781
|
+
const result = await runCli(args);
|
|
27782
|
+
if (result.exitCode !== 0) {
|
|
27783
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
27784
|
+
status: "error",
|
|
27785
|
+
exitCode: result.exitCode,
|
|
27786
|
+
stderrTail: result.stderr.trim().slice(-500)
|
|
27787
|
+
});
|
|
27788
|
+
return /* @__PURE__ */ new Set();
|
|
27789
|
+
}
|
|
27790
|
+
const line = /^cache-components=(.+)$/m.exec(result.stdout)?.[1];
|
|
27791
|
+
if (!line) {
|
|
27792
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
27793
|
+
status: "missing-output",
|
|
27794
|
+
exitCode: result.exitCode,
|
|
27795
|
+
cachedCount: 0
|
|
27796
|
+
});
|
|
27797
|
+
return /* @__PURE__ */ new Set();
|
|
27798
|
+
}
|
|
27799
|
+
try {
|
|
27800
|
+
const names = JSON.parse(line);
|
|
27801
|
+
const cachedNames = new Set(
|
|
27802
|
+
Array.isArray(names) ? names.filter((name) => typeof name === "string") : []
|
|
27803
|
+
);
|
|
27804
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
27805
|
+
status: "complete",
|
|
27806
|
+
exitCode: result.exitCode,
|
|
27807
|
+
cachedCount: cachedNames.size
|
|
27808
|
+
});
|
|
27809
|
+
return cachedNames;
|
|
27810
|
+
} catch {
|
|
27811
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
27812
|
+
status: "invalid-output",
|
|
27813
|
+
exitCode: result.exitCode,
|
|
27814
|
+
cachedCount: 0
|
|
27815
|
+
});
|
|
27816
|
+
return /* @__PURE__ */ new Set();
|
|
27817
|
+
}
|
|
27818
|
+
};
|
|
27819
|
+
useEffect15(() => {
|
|
27820
|
+
if (state.step !== "extracting" && state.step !== "scope-gate" || !state.extractSessionId || state.existingEntitiesStatus === "running" || state.existingEntitiesStatus === "idle" || state.selectionAgentStatus !== "complete" || state.compositionPhase !== "done" && state.compositionPhase !== "cache-hit" || state.rawTokensPath && state.tokenGenerationStatus !== "complete" || effectiveNoCache) {
|
|
27821
|
+
return;
|
|
27822
|
+
}
|
|
27823
|
+
const sessionId2 = state.extractSessionId;
|
|
27824
|
+
if (generationCachePreflightRef.current?.sessionId === sessionId2) return;
|
|
27825
|
+
const timer = startWizardTimer("generation-cache-preflight", { sessionId: sessionId2 });
|
|
27826
|
+
const db = openPipelineDb();
|
|
27827
|
+
let generatedNames = null;
|
|
27828
|
+
try {
|
|
27829
|
+
const rows = db.prepare("SELECT name, status FROM raw_components WHERE session_id = ?").all(sessionId2);
|
|
27830
|
+
if (rows.length > 0 && rows.every((row) => row.status === "generated")) {
|
|
27831
|
+
generatedNames = new Set(rows.map((row) => row.name));
|
|
27832
|
+
}
|
|
27833
|
+
} finally {
|
|
27834
|
+
db.close();
|
|
27835
|
+
}
|
|
27836
|
+
if (generatedNames) {
|
|
27837
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: Promise.resolve(generatedNames) };
|
|
27838
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
27839
|
+
status: "complete",
|
|
27840
|
+
source: "session-db",
|
|
27841
|
+
cachedCount: generatedNames.size
|
|
27842
|
+
});
|
|
27843
|
+
return;
|
|
27844
|
+
}
|
|
27845
|
+
const promise = checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
27846
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise };
|
|
27847
|
+
void promise.then((cachedNames) => {
|
|
27848
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
27849
|
+
status: "complete",
|
|
27850
|
+
source: "cache-status",
|
|
27851
|
+
cachedCount: cachedNames.size
|
|
27852
|
+
});
|
|
27853
|
+
});
|
|
27854
|
+
}, [
|
|
27855
|
+
state.step,
|
|
27856
|
+
state.extractSessionId,
|
|
27857
|
+
state.tokensPath,
|
|
27858
|
+
state.rawTokensPath,
|
|
27859
|
+
state.tokenGenerationStatus,
|
|
27860
|
+
state.selectionAgentStatus,
|
|
27861
|
+
state.compositionPhase,
|
|
27862
|
+
state.existingEntitiesStatus,
|
|
27863
|
+
state.existingEntitiesPath
|
|
27864
|
+
]);
|
|
27503
27865
|
const startGeneratePrefetch = (extractSessionId, tokensPath) => {
|
|
27504
27866
|
const args = buildGenerateArgs(extractSessionId, tokensPath);
|
|
27505
27867
|
let progressCursor = null;
|
|
@@ -27554,8 +27916,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
27554
27916
|
});
|
|
27555
27917
|
return donePromise;
|
|
27556
27918
|
};
|
|
27557
|
-
const runGenerate = async (extractSessionId, tokensPath, acceptedCount) => {
|
|
27558
|
-
const
|
|
27919
|
+
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false, cachedComponents = []) => {
|
|
27920
|
+
const timer = startWizardTimer("component-generation", {
|
|
27921
|
+
sessionId: extractSessionId,
|
|
27922
|
+
acceptedCount,
|
|
27923
|
+
suppressScreen,
|
|
27924
|
+
noCache: effectiveNoCache
|
|
27925
|
+
});
|
|
27926
|
+
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath, cachedComponents);
|
|
27559
27927
|
let progressCursor = state.generateProgress;
|
|
27560
27928
|
const { donePromise } = spawnGenerateChild({
|
|
27561
27929
|
command: "node",
|
|
@@ -27564,12 +27932,17 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
27564
27932
|
const nextProgress = parseGenerateStderrChunk(chunk, progressCursor);
|
|
27565
27933
|
if (nextProgress !== progressCursor) {
|
|
27566
27934
|
progressCursor = nextProgress;
|
|
27567
|
-
update({ generateProgress: nextProgress });
|
|
27935
|
+
if (!suppressScreen) update({ generateProgress: nextProgress });
|
|
27568
27936
|
}
|
|
27569
27937
|
}
|
|
27570
27938
|
});
|
|
27571
27939
|
const result = await donePromise;
|
|
27572
27940
|
if (result.exitCode !== 0) {
|
|
27941
|
+
finishWizardTimer("component-generation", timer, {
|
|
27942
|
+
status: "error",
|
|
27943
|
+
exitCode: result.exitCode
|
|
27944
|
+
});
|
|
27945
|
+
finishSelectionToReviewTimer("error");
|
|
27573
27946
|
update({
|
|
27574
27947
|
step: "error",
|
|
27575
27948
|
errorStep: "generate components",
|
|
@@ -27577,14 +27950,67 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
27577
27950
|
});
|
|
27578
27951
|
return;
|
|
27579
27952
|
}
|
|
27580
|
-
const { generateSessionId: generateSessionId2, generatedCount } = parseGenerateResult(result, acceptedCount);
|
|
27953
|
+
const { generateSessionId: generateSessionId2, generatedCount, renamedSlotsCount } = parseGenerateResult(result, acceptedCount);
|
|
27581
27954
|
const mappedSessionId = generateSessionId2 ?? extractSessionId;
|
|
27582
|
-
|
|
27583
|
-
|
|
27955
|
+
finishWizardTimer("component-generation", timer, {
|
|
27956
|
+
status: "complete",
|
|
27957
|
+
exitCode: result.exitCode,
|
|
27584
27958
|
generatedCount,
|
|
27585
|
-
|
|
27959
|
+
renamedSlotsCount
|
|
27586
27960
|
});
|
|
27587
|
-
if (
|
|
27961
|
+
if (!suppressScreen) {
|
|
27962
|
+
update({
|
|
27963
|
+
acceptedCount,
|
|
27964
|
+
autoRejectedCount: 0,
|
|
27965
|
+
generateSessionId: mappedSessionId,
|
|
27966
|
+
generatedCount,
|
|
27967
|
+
generateProgress: null
|
|
27968
|
+
});
|
|
27969
|
+
if (await runMapTokens2(mappedSessionId)) {
|
|
27970
|
+
finishSelectionToReviewTimer("generated");
|
|
27971
|
+
update({ step: "final-review" });
|
|
27972
|
+
} else {
|
|
27973
|
+
finishSelectionToReviewTimer("error");
|
|
27974
|
+
}
|
|
27975
|
+
return;
|
|
27976
|
+
}
|
|
27977
|
+
const mapped = await runMapTokens2(mappedSessionId, true);
|
|
27978
|
+
if (mapped) {
|
|
27979
|
+
finishSelectionToReviewTimer("generated");
|
|
27980
|
+
update(
|
|
27981
|
+
{
|
|
27982
|
+
acceptedCount,
|
|
27983
|
+
autoRejectedCount: 0,
|
|
27984
|
+
generateSessionId: mappedSessionId,
|
|
27985
|
+
generatedCount,
|
|
27986
|
+
generateProgress: null,
|
|
27987
|
+
mapTokensStatus: "complete",
|
|
27988
|
+
step: "final-review"
|
|
27989
|
+
},
|
|
27990
|
+
{ clearScreen: false }
|
|
27991
|
+
);
|
|
27992
|
+
} else {
|
|
27993
|
+
finishSelectionToReviewTimer("error");
|
|
27994
|
+
}
|
|
27995
|
+
};
|
|
27996
|
+
const finishCachedGeneration = async (sessionId2, acceptedCount) => {
|
|
27997
|
+
if (await runMapTokens2(sessionId2, true)) {
|
|
27998
|
+
finishSelectionToReviewTimer("cached");
|
|
27999
|
+
update(
|
|
28000
|
+
{
|
|
28001
|
+
acceptedCount,
|
|
28002
|
+
autoRejectedCount: 0,
|
|
28003
|
+
generateSessionId: sessionId2,
|
|
28004
|
+
generatedCount: acceptedCount,
|
|
28005
|
+
generateProgress: null,
|
|
28006
|
+
mapTokensStatus: "complete",
|
|
28007
|
+
step: "final-review"
|
|
28008
|
+
},
|
|
28009
|
+
{ clearScreen: false }
|
|
28010
|
+
);
|
|
28011
|
+
} else {
|
|
28012
|
+
finishSelectionToReviewTimer("error");
|
|
28013
|
+
}
|
|
27588
28014
|
};
|
|
27589
28015
|
const advanceToPushFlow = (generatedAcceptedCount) => {
|
|
27590
28016
|
update({ generatedAcceptedCount });
|
|
@@ -27769,8 +28195,15 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
27769
28195
|
return;
|
|
27770
28196
|
}
|
|
27771
28197
|
}
|
|
27772
|
-
if (await runAgentAuthCheck("generating")) {
|
|
27773
|
-
|
|
28198
|
+
if (await runAgentAuthCheck("generating", true)) {
|
|
28199
|
+
const cacheHit = await checkGenerateCache(sid, state.tokensPath);
|
|
28200
|
+
if (cacheHit) {
|
|
28201
|
+
update({ step: "generating" });
|
|
28202
|
+
void finishCachedGeneration(sid, state.acceptedCount);
|
|
28203
|
+
} else {
|
|
28204
|
+
update({ step: "generating" });
|
|
28205
|
+
void runGenerate(sid, state.tokensPath, state.acceptedCount);
|
|
28206
|
+
}
|
|
27774
28207
|
}
|
|
27775
28208
|
return;
|
|
27776
28209
|
}
|
|
@@ -28138,13 +28571,13 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28138
28571
|
update(nextStateAfterPrint({ skipGate: opts.skipGate, componentsPath }));
|
|
28139
28572
|
return { ok: true };
|
|
28140
28573
|
};
|
|
28141
|
-
const runSaveAndPush = async () => {
|
|
28142
|
-
await startSaveFlow({ skipGate: true, andPush: true });
|
|
28574
|
+
const runSaveAndPush = async (statePatch = {}) => {
|
|
28575
|
+
await startSaveFlow({ skipGate: true, andPush: true }, statePatch);
|
|
28143
28576
|
};
|
|
28144
28577
|
const pendingSaveOptionsRef = useRef10({});
|
|
28145
|
-
const startSaveFlow = async (opts = {}) => {
|
|
28578
|
+
const startSaveFlow = async (opts = {}, statePatch = {}) => {
|
|
28146
28579
|
pendingSaveOptionsRef.current = opts;
|
|
28147
|
-
|
|
28580
|
+
update({ ...statePatch, step: "path-prompt" });
|
|
28148
28581
|
};
|
|
28149
28582
|
const proceedToWrite = async (path) => {
|
|
28150
28583
|
setState((prev) => ({ ...prev, outDir: path }));
|
|
@@ -28387,31 +28820,86 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28387
28820
|
{
|
|
28388
28821
|
components,
|
|
28389
28822
|
onConfirm: (decisions) => {
|
|
28390
|
-
void
|
|
28391
|
-
|
|
28392
|
-
|
|
28393
|
-
|
|
28394
|
-
|
|
28395
|
-
|
|
28396
|
-
|
|
28397
|
-
|
|
28398
|
-
|
|
28399
|
-
|
|
28400
|
-
|
|
28401
|
-
|
|
28402
|
-
|
|
28403
|
-
|
|
28823
|
+
void (async () => {
|
|
28824
|
+
selectionToReviewStartedAtRef.current = decisions.accepted.length > 0 ? startWizardTimer("selection-to-review", {
|
|
28825
|
+
sessionId: sessionId2,
|
|
28826
|
+
acceptedCount: decisions.accepted.length,
|
|
28827
|
+
rejectedCount: decisions.rejected.length
|
|
28828
|
+
}) : null;
|
|
28829
|
+
const preflight = generationCachePreflightRef.current;
|
|
28830
|
+
const cachePromise = preflight?.sessionId === sessionId2 ? preflight.promise : checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
28831
|
+
if (!preflight || preflight.sessionId !== sessionId2) {
|
|
28832
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: cachePromise };
|
|
28833
|
+
}
|
|
28834
|
+
const cacheWaitStartedAt = startWizardTimer("selection-cache-restoration-wait", {
|
|
28835
|
+
sessionId: sessionId2,
|
|
28836
|
+
preflight: Boolean(preflight?.sessionId === sessionId2)
|
|
28837
|
+
});
|
|
28838
|
+
try {
|
|
28839
|
+
const cachedNames = await cachePromise;
|
|
28840
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
28841
|
+
status: "complete",
|
|
28842
|
+
cachedCount: cachedNames.size
|
|
28843
|
+
});
|
|
28844
|
+
} catch (error) {
|
|
28845
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
28846
|
+
status: "error",
|
|
28847
|
+
error: error instanceof Error ? error.message : String(error)
|
|
28848
|
+
});
|
|
28849
|
+
finishSelectionToReviewTimer("error");
|
|
28850
|
+
throw error;
|
|
28851
|
+
}
|
|
28852
|
+
await runScopeGate({
|
|
28853
|
+
sessionId: sessionId2,
|
|
28854
|
+
decisions,
|
|
28855
|
+
onAdvanceToGenerate: async ({ sessionId: sid, acceptedCount }) => {
|
|
28856
|
+
scopeGateCompletedRef.current = true;
|
|
28857
|
+
if (shouldGenerateAfterScopeGate({ acceptedCount })) {
|
|
28858
|
+
const authPromise = runAgentAuthCheck("generating", true);
|
|
28859
|
+
if (await authPromise) {
|
|
28860
|
+
const comparisonStartedAt = startWizardTimer("generation-cache-set-comparison", {
|
|
28861
|
+
sessionId: sid,
|
|
28862
|
+
acceptedCount: decisions?.accepted.length ?? 0
|
|
28863
|
+
});
|
|
28864
|
+
let cachedNames = await cachePromise;
|
|
28865
|
+
const acceptedNames = decisions?.accepted ?? [];
|
|
28866
|
+
let cacheHit = !effectiveNoCache && acceptedNames.length > 0 && acceptedNames.every((name) => cachedNames.has(name));
|
|
28867
|
+
if (!cacheHit && !effectiveNoCache && acceptedNames.length > 0) {
|
|
28868
|
+
cachedNames = await checkGenerateCacheComponents(sid, state.tokensPath, true);
|
|
28869
|
+
cacheHit = acceptedNames.every((name) => cachedNames.has(name));
|
|
28870
|
+
}
|
|
28871
|
+
finishWizardTimer("generation-cache-set-comparison", comparisonStartedAt, {
|
|
28872
|
+
status: "complete",
|
|
28873
|
+
cacheHit,
|
|
28874
|
+
cachedCount: cachedNames.size,
|
|
28875
|
+
acceptedCount: acceptedNames.length
|
|
28876
|
+
});
|
|
28877
|
+
if (cacheHit) {
|
|
28878
|
+
void finishCachedGeneration(sid, acceptedCount);
|
|
28879
|
+
} else {
|
|
28880
|
+
const acceptedNameSet = new Set(acceptedNames);
|
|
28881
|
+
const restoredCachedNames = [...cachedNames].filter((name) => acceptedNameSet.has(name));
|
|
28882
|
+
update({
|
|
28883
|
+
step: "generating",
|
|
28884
|
+
generateProgress: null,
|
|
28885
|
+
acceptedCount
|
|
28886
|
+
});
|
|
28887
|
+
void runGenerate(sid, state.tokensPath, acceptedCount, false, restoredCachedNames);
|
|
28888
|
+
}
|
|
28889
|
+
} else {
|
|
28890
|
+
finishSelectionToReviewTimer("error");
|
|
28891
|
+
}
|
|
28892
|
+
return;
|
|
28404
28893
|
}
|
|
28405
|
-
|
|
28894
|
+
void runSaveAndPush();
|
|
28895
|
+
},
|
|
28896
|
+
onAdvanceToPushFlow: (count) => {
|
|
28897
|
+
scopeGateCompletedRef.current = true;
|
|
28898
|
+
update({ acceptedCount: count, autoRejectedCount: 0 });
|
|
28899
|
+
advanceToPushFlow(count);
|
|
28406
28900
|
}
|
|
28407
|
-
|
|
28408
|
-
|
|
28409
|
-
onAdvanceToPushFlow: (count) => {
|
|
28410
|
-
scopeGateCompletedRef.current = true;
|
|
28411
|
-
update({ acceptedCount: count, autoRejectedCount: 0 });
|
|
28412
|
-
advanceToPushFlow(count);
|
|
28413
|
-
}
|
|
28414
|
-
});
|
|
28901
|
+
});
|
|
28902
|
+
})();
|
|
28415
28903
|
},
|
|
28416
28904
|
onQuit: () => process.exit(0)
|
|
28417
28905
|
}
|
|
@@ -28498,8 +28986,10 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28498
28986
|
}
|
|
28499
28987
|
const allowEmptyDeleteAll = acceptedCount === 0;
|
|
28500
28988
|
allowEmptyDeleteAllRef.current = allowEmptyDeleteAll;
|
|
28501
|
-
|
|
28502
|
-
|
|
28989
|
+
void runSaveAndPush({
|
|
28990
|
+
finalReviewPassed: true,
|
|
28991
|
+
generatedAcceptedCount: acceptedCount
|
|
28992
|
+
});
|
|
28503
28993
|
},
|
|
28504
28994
|
onQuit: () => process.exit(0)
|
|
28505
28995
|
}
|
|
@@ -28738,6 +29228,7 @@ var init_WizardApp = __esm({
|
|
|
28738
29228
|
init_prompt_overrides();
|
|
28739
29229
|
init_run_selection_agent();
|
|
28740
29230
|
init_use_terminal_size();
|
|
29231
|
+
init_render_with_goodbye();
|
|
28741
29232
|
SAVE_CONFIRMATION_DELAY_MS = 1e3;
|
|
28742
29233
|
WIZARD_LOG = join20(tmpdir(), "experiences-import-wizard.log");
|
|
28743
29234
|
}
|
package/dist/src/session/db.d.ts
CHANGED
|
@@ -122,6 +122,14 @@ export declare function computeMapTokensInputHash(db: DatabaseSync, sessionId: s
|
|
|
122
122
|
export declare function lookupCache(db: DatabaseSync, inputHash: string, entityType: CacheEntityType, entityId: string, promptHash?: string): CacheEntry | null;
|
|
123
123
|
export declare function lookupCacheByEntity(db: DatabaseSync, entityType: CacheEntityType, entityId: string): CacheEntry | null;
|
|
124
124
|
export declare function storeCache(db: DatabaseSync, inputHash: string, entityType: CacheEntityType, entityId: string, sourceSessionId: string, humanEdited: boolean, promptHash?: string): void;
|
|
125
|
+
export declare function storeCaches(db: DatabaseSync, entries: Array<{
|
|
126
|
+
inputHash: string;
|
|
127
|
+
entityType: CacheEntityType;
|
|
128
|
+
entityId: string;
|
|
129
|
+
sourceSessionId: string;
|
|
130
|
+
humanEdited: boolean;
|
|
131
|
+
promptHash?: string;
|
|
132
|
+
}>): void;
|
|
125
133
|
export declare function storeScannedFiles(db: DatabaseSync, sessionId: string, filePaths: string[]): void;
|
|
126
134
|
export declare function loadScannedFiles(db: DatabaseSync, sessionId: string): string[];
|
|
127
135
|
export declare function storeSlotCycles(db: DatabaseSync, sessionId: string, cycles: Array<SlotCycle & {
|
|
@@ -133,7 +141,12 @@ export interface StoredSlotCycle extends SlotCycle {
|
|
|
133
141
|
export declare function loadSlotCycles(db: DatabaseSync, sessionId: string): StoredSlotCycle[];
|
|
134
142
|
export declare function clearSlotCycles(db: DatabaseSync, sessionId: string): void;
|
|
135
143
|
export declare function markCacheHumanEdited(db: DatabaseSync, entityType: 'component' | 'token_set', entityId: string): void;
|
|
136
|
-
export declare function copyComponentFromCache(db: DatabaseSync, sourceSessionId: string, targetSessionId: string, componentId: string): void;
|
|
144
|
+
export declare function copyComponentFromCache(db: DatabaseSync, sourceSessionId: string, targetSessionId: string, componentId: string, manageTransaction?: boolean): void;
|
|
145
|
+
export declare function copyComponentsFromCache(db: DatabaseSync, entries: Array<{
|
|
146
|
+
sourceSessionId: string;
|
|
147
|
+
targetSessionId: string;
|
|
148
|
+
componentId: string;
|
|
149
|
+
}>): void;
|
|
137
150
|
export declare function copyTokensFromCache(db: DatabaseSync, sourceSessionId: string, targetSessionId: string): void;
|
|
138
151
|
export declare function copyMapTokensFromCache(db: DatabaseSync, sourceSessionId: string, targetSessionId: string): number;
|
|
139
152
|
export declare function getCliCacheVersion(): Promise<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/experience-design-system-cli",
|
|
3
|
-
"version": "2.34.5-dev-build-
|
|
3
|
+
"version": "2.34.5-dev-build-a95aeeba.0",
|
|
4
4
|
"description": "Contentful Experiences design system import CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"svelte": "^5.56.4",
|
|
42
42
|
"ts-morph": "^27.0.2",
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
|
-
"@contentful/experience-design-system-
|
|
45
|
-
"@contentful/experience-design-system-
|
|
44
|
+
"@contentful/experience-design-system-types": "2.34.5-dev-build-a95aeeba.0",
|
|
45
|
+
"@contentful/experience-design-system-cli-v2": "2.34.5-dev-build-a95aeeba.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@tsconfig/node24": "^24.0.4",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"ink-testing-library": "^4.0.0",
|
|
55
55
|
"typescript-eslint": "^8.67.0",
|
|
56
56
|
"vitest": "^4.0.16",
|
|
57
|
-
"@contentful/experience-design-system-extraction": "2.34.5-dev-build-
|
|
58
|
-
"@contentful/experience-design-system-
|
|
59
|
-
"@contentful/experience-design-system-
|
|
57
|
+
"@contentful/experience-design-system-extraction": "2.34.5-dev-build-a95aeeba.0",
|
|
58
|
+
"@contentful/experience-design-system-client": "2.34.5-dev-build-a95aeeba.0",
|
|
59
|
+
"@contentful/experience-design-system-generation": "2.34.5-dev-build-a95aeeba.0"
|
|
60
60
|
},
|
|
61
61
|
"repository": {
|
|
62
62
|
"type": "git",
|