@contentful/experience-design-system-cli 2.35.1-dev-build-a91cc5b7.0 → 2.35.1-dev-build-4f1ad8cb.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 +1 -5
- package/dist/src/tui/home/home.d.ts +0 -1
- package/dist/src/tui/home/home.theme.d.ts +0 -11
- package/legacy/dist/src/analyze/extract-command.d.ts +4 -0
- package/legacy/dist/src/import/tui/WizardApp.d.ts +7 -1
- package/legacy/dist/src/import/tui/run-selection-agent.d.ts +1 -0
- package/legacy/dist/src/import/tui/wizard-state-transitions.d.ts +3 -0
- package/legacy/dist/src/index.js +1325 -209
- package/legacy/dist/src/map-tokens/tui/MapTokensView.d.ts +1 -0
- package/legacy/dist/src/session/cache-keys.d.ts +22 -0
- package/legacy/dist/src/session/core/components/hash-component-shape.d.ts +5 -0
- package/legacy/dist/src/session/core/tokens/hash-token-content.d.ts +1 -0
- package/legacy/dist/src/session/db.d.ts +72 -2
- package/legacy/package.json +1 -5
- package/package.json +3 -7
- package/legacy/skills/debate-select.md +0 -23
package/legacy/dist/src/index.js
CHANGED
|
@@ -164,11 +164,12 @@ var init_render_with_goodbye = __esm({
|
|
|
164
164
|
function isAgentName(value) {
|
|
165
165
|
return AGENT_NAMES.includes(value);
|
|
166
166
|
}
|
|
167
|
-
var AGENT_NAMES, AGENT_BINARIES;
|
|
167
|
+
var AGENT_NAMES, DEFAULT_AGENT_NAME, AGENT_BINARIES;
|
|
168
168
|
var init_agent_names = __esm({
|
|
169
169
|
"packages/experience-design-system-generation/dist/src/agent-names.js"() {
|
|
170
170
|
"use strict";
|
|
171
171
|
AGENT_NAMES = ["claude", "codex", "opencode", "cursor", "copilot"];
|
|
172
|
+
DEFAULT_AGENT_NAME = "claude";
|
|
172
173
|
AGENT_BINARIES = {
|
|
173
174
|
claude: "claude",
|
|
174
175
|
codex: "codex",
|
|
@@ -180,6 +181,23 @@ var init_agent_names = __esm({
|
|
|
180
181
|
});
|
|
181
182
|
|
|
182
183
|
// packages/experience-design-system-generation/dist/src/controller/helpers/validate-generation-request.js
|
|
184
|
+
function validateGenerationRequest(request2) {
|
|
185
|
+
if (request2 === null || typeof request2 !== "object") {
|
|
186
|
+
throw new TypeError("createGenerationEndpoint requires a request object");
|
|
187
|
+
}
|
|
188
|
+
if (!isAgentName(request2.agent)) {
|
|
189
|
+
throw new TypeError(`createGenerationEndpoint requires agent to be a valid agent name, got: ${String(request2.agent)}`);
|
|
190
|
+
}
|
|
191
|
+
if (typeof request2.timeoutMs !== "number" || request2.timeoutMs <= 0) {
|
|
192
|
+
throw new TypeError("createGenerationEndpoint requires timeoutMs to be a positive number");
|
|
193
|
+
}
|
|
194
|
+
if (request2.promptOptions === null || typeof request2.promptOptions !== "object") {
|
|
195
|
+
throw new TypeError("createGenerationEndpoint requires promptOptions to be an object");
|
|
196
|
+
}
|
|
197
|
+
if (request2.onOutput !== void 0 && typeof request2.onOutput !== "function") {
|
|
198
|
+
throw new TypeError("createGenerationEndpoint requires onOutput to be a function when provided");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
183
201
|
var init_validate_generation_request = __esm({
|
|
184
202
|
"packages/experience-design-system-generation/dist/src/controller/helpers/validate-generation-request.js"() {
|
|
185
203
|
"use strict";
|
|
@@ -238,7 +256,6 @@ var init_resolve_skill_file = __esm({
|
|
|
238
256
|
components: "generate-components.md",
|
|
239
257
|
tokens: "generate-tokens.md",
|
|
240
258
|
select: "select-components.md",
|
|
241
|
-
"debate-select": "debate-select.md",
|
|
242
259
|
"map-tokens": "map-tokens.md"
|
|
243
260
|
};
|
|
244
261
|
}
|
|
@@ -500,31 +517,6 @@ Rules:
|
|
|
500
517
|
- Emit set_group calls before the set_token calls that fall under them.
|
|
501
518
|
- You may emit prose lines (not starting with {) anywhere \u2014 they are ignored by the parser and serve as your reasoning log.`;
|
|
502
519
|
}
|
|
503
|
-
function buildDebateSelectAutonomousPreamble(inputBlock, debateRole, disagreementInline) {
|
|
504
|
-
const role = debateRole ?? "for";
|
|
505
|
-
return [
|
|
506
|
-
"You are the " + role.toUpperCase() + " participant in an adversarial review of one component-selection disagreement. This is an automatic escalation stage; do not ask the developer for confirmation.",
|
|
507
|
-
"",
|
|
508
|
-
"Your role is to argue the " + role.toUpperCase() + " position on the exact disagreement below. Address the claim literally, cite the supplied component evidence, and do not substitute a nearby component or field. The opposing participant is evaluating the same evidence independently.",
|
|
509
|
-
"",
|
|
510
|
-
"Component and source data:" + inputBlock,
|
|
511
|
-
"",
|
|
512
|
-
"Disagreement under review (JSON):",
|
|
513
|
-
"~~~json",
|
|
514
|
-
disagreementInline ?? "{}",
|
|
515
|
-
"~~~",
|
|
516
|
-
"",
|
|
517
|
-
"## Output protocol",
|
|
518
|
-
"",
|
|
519
|
-
"Emit exactly one JSON object on one line and do not write files:",
|
|
520
|
-
"",
|
|
521
|
-
"~~~json",
|
|
522
|
-
'{"role":"' + role + '","disagreement_id":"<id>","argument":"<position and reasoning>","evidence":[{"source":"<path>","line":"<line-or-range>","quote":"<verbatim evidence>"}]}',
|
|
523
|
-
"~~~",
|
|
524
|
-
"",
|
|
525
|
-
"The role and disagreement_id must match the values in this prompt. Use an empty evidence array only when the supplied context contains no citable source evidence."
|
|
526
|
-
].join("\n");
|
|
527
|
-
}
|
|
528
520
|
var init_build_skill_preambles = __esm({
|
|
529
521
|
"packages/experience-design-system-generation/dist/src/services/prompts/helpers/build-skill-preambles.js"() {
|
|
530
522
|
"use strict";
|
|
@@ -533,7 +525,7 @@ var init_build_skill_preambles = __esm({
|
|
|
533
525
|
|
|
534
526
|
// packages/experience-design-system-generation/dist/src/services/prompts/helpers/build-preamble.js
|
|
535
527
|
function buildPreamble(options) {
|
|
536
|
-
const { skill, rawComponentsInline, propBucketsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs, existingComponentsInline, existingTokensInline, componentAllowlistInline
|
|
528
|
+
const { skill, rawComponentsInline, propBucketsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs, existingComponentsInline, existingTokensInline, componentAllowlistInline } = options;
|
|
537
529
|
const sections = [];
|
|
538
530
|
if (existingComponentsInline) {
|
|
539
531
|
sections.push(`Existing components in the target Contentful space (JSON) \u2014 use for alignment, not as a hard filter:
|
|
@@ -605,8 +597,6 @@ ${sections.join("\n\n")}` : "";
|
|
|
605
597
|
return buildComponentsAutonomousPreamble(inputBlock);
|
|
606
598
|
if (skill === "select")
|
|
607
599
|
return buildSelectAutonomousPreamble(inputBlock);
|
|
608
|
-
if (skill === "debate-select")
|
|
609
|
-
return buildDebateSelectAutonomousPreamble(inputBlock, debateRole, disagreementInline);
|
|
610
600
|
if (skill === "map-tokens")
|
|
611
601
|
return buildMapTokensAutonomousPreamble(inputBlock);
|
|
612
602
|
return buildTokensAutonomousPreamble(inputBlock);
|
|
@@ -640,6 +630,17 @@ var init_build_prompt = __esm({
|
|
|
640
630
|
});
|
|
641
631
|
|
|
642
632
|
// packages/experience-design-system-generation/dist/src/orchestrator/execute-generation-orchestrator.js
|
|
633
|
+
async function executeGenerationOrchestrator(request2) {
|
|
634
|
+
const prompt = await buildPrompt(request2.promptOptions);
|
|
635
|
+
return request2.invoker.invoke({
|
|
636
|
+
agent: request2.agent,
|
|
637
|
+
model: request2.model,
|
|
638
|
+
bedrock: request2.bedrock,
|
|
639
|
+
prompt,
|
|
640
|
+
timeoutMs: request2.timeoutMs,
|
|
641
|
+
onOutput: request2.onOutput
|
|
642
|
+
});
|
|
643
|
+
}
|
|
643
644
|
var init_execute_generation_orchestrator = __esm({
|
|
644
645
|
"packages/experience-design-system-generation/dist/src/orchestrator/execute-generation-orchestrator.js"() {
|
|
645
646
|
"use strict";
|
|
@@ -740,6 +741,22 @@ var init_describe_agent_failure = __esm({
|
|
|
740
741
|
});
|
|
741
742
|
|
|
742
743
|
// packages/experience-design-system-generation/dist/src/services/agent/helpers/extract-sentinel-output.js
|
|
744
|
+
function extractSentinelOutput(stdout) {
|
|
745
|
+
const START = "<<<EDS_OUTPUT_START>>>";
|
|
746
|
+
const END = "<<<EDS_OUTPUT_END>>>";
|
|
747
|
+
const startIdx = stdout.indexOf(START);
|
|
748
|
+
const endIdx = stdout.indexOf(END);
|
|
749
|
+
if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx)
|
|
750
|
+
return null;
|
|
751
|
+
const secondStart = stdout.indexOf(START, startIdx + START.length);
|
|
752
|
+
if (secondStart !== -1 && secondStart < endIdx)
|
|
753
|
+
return "multiple";
|
|
754
|
+
const afterStart = stdout.indexOf(END, startIdx);
|
|
755
|
+
const secondEnd = stdout.indexOf(END, afterStart + END.length);
|
|
756
|
+
if (secondEnd !== -1)
|
|
757
|
+
return "multiple";
|
|
758
|
+
return stdout.slice(startIdx + START.length, endIdx).trim();
|
|
759
|
+
}
|
|
743
760
|
var init_extract_sentinel_output = __esm({
|
|
744
761
|
"packages/experience-design-system-generation/dist/src/services/agent/helpers/extract-sentinel-output.js"() {
|
|
745
762
|
"use strict";
|
|
@@ -764,7 +781,7 @@ async function runAgent(options) {
|
|
|
764
781
|
promptLen: prompt.length,
|
|
765
782
|
promptHead: prompt.slice(0, 500)
|
|
766
783
|
});
|
|
767
|
-
return new Promise((
|
|
784
|
+
return new Promise((resolve21) => {
|
|
768
785
|
const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
|
|
769
786
|
const child = spawn(binary, args, {
|
|
770
787
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -813,7 +830,7 @@ async function runAgent(options) {
|
|
|
813
830
|
stderrLen: stderr.length,
|
|
814
831
|
stderrTail: stderr.slice(-1e3)
|
|
815
832
|
});
|
|
816
|
-
|
|
833
|
+
resolve21(result);
|
|
817
834
|
});
|
|
818
835
|
});
|
|
819
836
|
}
|
|
@@ -830,7 +847,7 @@ var init_run_agent = __esm({
|
|
|
830
847
|
// packages/experience-design-system-generation/dist/src/services/agent/helpers/check-claude-auth.js
|
|
831
848
|
import { spawn as spawn2 } from "node:child_process";
|
|
832
849
|
function checkClaudeAuth(binary) {
|
|
833
|
-
return new Promise((
|
|
850
|
+
return new Promise((resolve21) => {
|
|
834
851
|
const child = spawn2(binary, ["auth", "status", "--json"], {
|
|
835
852
|
stdio: ["ignore", "pipe", "pipe"]
|
|
836
853
|
});
|
|
@@ -840,7 +857,7 @@ function checkClaudeAuth(binary) {
|
|
|
840
857
|
if (!done) {
|
|
841
858
|
done = true;
|
|
842
859
|
child.kill("SIGTERM");
|
|
843
|
-
|
|
860
|
+
resolve21("unauthenticated");
|
|
844
861
|
}
|
|
845
862
|
}, 5e3);
|
|
846
863
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -852,14 +869,14 @@ function checkClaudeAuth(binary) {
|
|
|
852
869
|
done = true;
|
|
853
870
|
clearTimeout(timer);
|
|
854
871
|
if (code !== 0) {
|
|
855
|
-
|
|
872
|
+
resolve21("unauthenticated");
|
|
856
873
|
return;
|
|
857
874
|
}
|
|
858
875
|
try {
|
|
859
876
|
const status = JSON.parse(stdout);
|
|
860
|
-
|
|
877
|
+
resolve21(status.loggedIn ? "ok" : "unauthenticated");
|
|
861
878
|
} catch {
|
|
862
|
-
|
|
879
|
+
resolve21("unauthenticated");
|
|
863
880
|
}
|
|
864
881
|
});
|
|
865
882
|
});
|
|
@@ -874,13 +891,13 @@ var init_check_claude_auth = __esm({
|
|
|
874
891
|
import { spawn as spawn3 } from "node:child_process";
|
|
875
892
|
async function checkAgentAuth(agent) {
|
|
876
893
|
const binary = resolveAgentBinary(agent);
|
|
877
|
-
const binaryExists2 = await new Promise((
|
|
894
|
+
const binaryExists2 = await new Promise((resolve21) => {
|
|
878
895
|
if (binary.startsWith("/")) {
|
|
879
|
-
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() =>
|
|
896
|
+
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() => resolve21(true), () => resolve21(false)));
|
|
880
897
|
return;
|
|
881
898
|
}
|
|
882
899
|
const child = spawn3(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
|
|
883
|
-
child.on("close", (code) =>
|
|
900
|
+
child.on("close", (code) => resolve21(code === 0));
|
|
884
901
|
});
|
|
885
902
|
if (!binaryExists2)
|
|
886
903
|
return "not-found";
|
|
@@ -917,6 +934,20 @@ var init_local_cli_agent_invoker = __esm({
|
|
|
917
934
|
});
|
|
918
935
|
|
|
919
936
|
// packages/experience-design-system-generation/dist/src/controller/create-generation-endpoint.js
|
|
937
|
+
function createGenerationEndpoint(options = {}) {
|
|
938
|
+
const invoker2 = createLocalCliAgentInvoker({
|
|
939
|
+
onDebugEvent: options.onDebugEvent
|
|
940
|
+
});
|
|
941
|
+
return {
|
|
942
|
+
async run(request2) {
|
|
943
|
+
validateGenerationRequest(request2);
|
|
944
|
+
return executeGenerationOrchestrator({ ...request2, invoker: invoker2 });
|
|
945
|
+
},
|
|
946
|
+
checkAuth(agent) {
|
|
947
|
+
return invoker2.checkAuth(agent);
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
}
|
|
920
951
|
var init_create_generation_endpoint = __esm({
|
|
921
952
|
"packages/experience-design-system-generation/dist/src/controller/create-generation-endpoint.js"() {
|
|
922
953
|
"use strict";
|
|
@@ -1301,6 +1332,32 @@ var init_progress = __esm({
|
|
|
1301
1332
|
});
|
|
1302
1333
|
|
|
1303
1334
|
// packages/experience-design-system-generation/dist/src/index.js
|
|
1335
|
+
var src_exports = {};
|
|
1336
|
+
__export(src_exports, {
|
|
1337
|
+
AGENT_BINARIES: () => AGENT_BINARIES,
|
|
1338
|
+
AGENT_NAMES: () => AGENT_NAMES,
|
|
1339
|
+
DEFAULT_AGENT_NAME: () => DEFAULT_AGENT_NAME,
|
|
1340
|
+
agentSupportsBedrock: () => agentSupportsBedrock,
|
|
1341
|
+
buildArgs: () => buildAgentArgs,
|
|
1342
|
+
buildPrompt: () => buildPrompt,
|
|
1343
|
+
checkAgentAuth: () => checkAgentAuth,
|
|
1344
|
+
createGenerationEndpoint: () => createGenerationEndpoint,
|
|
1345
|
+
createLocalCliAgentInvoker: () => createLocalCliAgentInvoker,
|
|
1346
|
+
describeAgentFailure: () => describeAgentFailure,
|
|
1347
|
+
executeGenerationOrchestrator: () => executeGenerationOrchestrator,
|
|
1348
|
+
extractSentinelOutput: () => extractSentinelOutput,
|
|
1349
|
+
formatCustomPromptBanner: () => formatCustomPromptBanner,
|
|
1350
|
+
formatGenerateProgressLine: () => formatGenerateProgressLine,
|
|
1351
|
+
isAgentName: () => isAgentName,
|
|
1352
|
+
parseMapTokenPropToolCallLines: () => parseMapTokenPropToolCallLines,
|
|
1353
|
+
parseSelectToolCallLines: () => parseSelectToolCallLines,
|
|
1354
|
+
parseTokenToolCallLines: () => parseTokenToolCallLines,
|
|
1355
|
+
parseToolCallLines: () => parsePropToolCallLines,
|
|
1356
|
+
resolveAgentModel: () => resolveAgentModel,
|
|
1357
|
+
resolveBinary: () => resolveAgentBinary,
|
|
1358
|
+
resolveSkillPath: () => resolveSkillPath,
|
|
1359
|
+
runAgent: () => runAgent
|
|
1360
|
+
});
|
|
1304
1361
|
var init_src = __esm({
|
|
1305
1362
|
"packages/experience-design-system-generation/dist/src/index.js"() {
|
|
1306
1363
|
"use strict";
|
|
@@ -10336,6 +10393,41 @@ var init_read3 = __esm({
|
|
|
10336
10393
|
}
|
|
10337
10394
|
});
|
|
10338
10395
|
|
|
10396
|
+
// packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts
|
|
10397
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
10398
|
+
function hashComponentShape(component) {
|
|
10399
|
+
const payload = {
|
|
10400
|
+
framework: component.framework,
|
|
10401
|
+
name: component.name,
|
|
10402
|
+
source: component.source,
|
|
10403
|
+
props: component.props.map((p) => ({
|
|
10404
|
+
name: p.name,
|
|
10405
|
+
type: p.type
|
|
10406
|
+
})),
|
|
10407
|
+
slots: component.slots.map((s) => ({
|
|
10408
|
+
name: s.name,
|
|
10409
|
+
isDefault: s.isDefault
|
|
10410
|
+
}))
|
|
10411
|
+
};
|
|
10412
|
+
return createHash2("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
10413
|
+
}
|
|
10414
|
+
var init_hash_component_shape = __esm({
|
|
10415
|
+
"packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts"() {
|
|
10416
|
+
"use strict";
|
|
10417
|
+
}
|
|
10418
|
+
});
|
|
10419
|
+
|
|
10420
|
+
// packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts
|
|
10421
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
10422
|
+
function hashTokenContent(rawTokenContent) {
|
|
10423
|
+
return createHash3("sha256").update(rawTokenContent.trim()).digest("hex");
|
|
10424
|
+
}
|
|
10425
|
+
var init_hash_token_content = __esm({
|
|
10426
|
+
"packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts"() {
|
|
10427
|
+
"use strict";
|
|
10428
|
+
}
|
|
10429
|
+
});
|
|
10430
|
+
|
|
10339
10431
|
// packages/experience-design-system-cli-legacy/src/session/repositories/tokens/write.ts
|
|
10340
10432
|
function deleteRawTokensForSession(db, sessionId2) {
|
|
10341
10433
|
db.prepare("DELETE FROM raw_token_groups WHERE session_id = ?").run(sessionId2);
|
|
@@ -10499,17 +10591,47 @@ var init_replace_raw_prop_token_paths = __esm({
|
|
|
10499
10591
|
}
|
|
10500
10592
|
});
|
|
10501
10593
|
|
|
10594
|
+
// packages/experience-design-system-cli-legacy/src/session/cache-keys.ts
|
|
10595
|
+
var cache_keys_exports = {};
|
|
10596
|
+
__export(cache_keys_exports, {
|
|
10597
|
+
hashContent: () => hashContent,
|
|
10598
|
+
hashFile: () => hashFile,
|
|
10599
|
+
hashPromptForSkill: () => hashPromptForSkill
|
|
10600
|
+
});
|
|
10601
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
10602
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
10603
|
+
import { resolve as resolve8 } from "node:path";
|
|
10604
|
+
function hashContent(content) {
|
|
10605
|
+
return createHash4("sha256").update(content).digest("hex");
|
|
10606
|
+
}
|
|
10607
|
+
async function hashFile(filePath) {
|
|
10608
|
+
const content = await readFile7(filePath, "utf8");
|
|
10609
|
+
return hashContent(content);
|
|
10610
|
+
}
|
|
10611
|
+
async function hashPromptForSkill(skill, agent, model, skillPathOverride, extraInputs = [], skillContentOverride) {
|
|
10612
|
+
const promptHash = skillContentOverride ? hashContent(skillContentOverride) : skillPathOverride ? await hashFile(resolve8(skillPathOverride)) : await hashFile(resolveSkillPath(skill));
|
|
10613
|
+
const extraSegment = extraInputs.length > 0 ? `|${extraInputs.join("|")}` : "";
|
|
10614
|
+
return hashContent(`${promptHash}|${agent}|${model ?? ""}${extraSegment}`);
|
|
10615
|
+
}
|
|
10616
|
+
var init_cache_keys = __esm({
|
|
10617
|
+
"packages/experience-design-system-cli-legacy/src/session/cache-keys.ts"() {
|
|
10618
|
+
"use strict";
|
|
10619
|
+
init_src();
|
|
10620
|
+
}
|
|
10621
|
+
});
|
|
10622
|
+
|
|
10502
10623
|
// packages/experience-design-system-cli-legacy/src/session/db.ts
|
|
10503
10624
|
import { DatabaseSync } from "node:sqlite";
|
|
10504
10625
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
10505
|
-
import { readFile as
|
|
10626
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
10627
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
10506
10628
|
import { homedir as homedir3 } from "node:os";
|
|
10507
|
-
import { dirname as dirname14, resolve as
|
|
10629
|
+
import { dirname as dirname14, resolve as resolve9 } from "node:path";
|
|
10508
10630
|
function getPipelineDbPath() {
|
|
10509
10631
|
if (process.env.EDS_PIPELINE_DB_PATH) {
|
|
10510
|
-
return
|
|
10632
|
+
return resolve9(process.env.EDS_PIPELINE_DB_PATH);
|
|
10511
10633
|
}
|
|
10512
|
-
return
|
|
10634
|
+
return resolve9(homedir3(), ".contentful", "experience-design-system-cli", "pipeline.db");
|
|
10513
10635
|
}
|
|
10514
10636
|
function openPipelineDb(dbPath) {
|
|
10515
10637
|
const path = dbPath ?? getPipelineDbPath();
|
|
@@ -10643,8 +10765,134 @@ function applyDbMigrations(db) {
|
|
|
10643
10765
|
if (!rawSlotColsForRationale.some((c2) => c2.name === "rationale")) {
|
|
10644
10766
|
db.exec("ALTER TABLE raw_slots ADD COLUMN rationale TEXT");
|
|
10645
10767
|
}
|
|
10646
|
-
|
|
10647
|
-
|
|
10768
|
+
const hasExtractCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='extract_cache'`).all();
|
|
10769
|
+
if (hasExtractCache.length === 0) {
|
|
10770
|
+
db.exec(`
|
|
10771
|
+
CREATE TABLE extract_cache (
|
|
10772
|
+
file_path TEXT NOT NULL,
|
|
10773
|
+
file_hash TEXT NOT NULL,
|
|
10774
|
+
cli_version TEXT NOT NULL,
|
|
10775
|
+
created_at TEXT NOT NULL,
|
|
10776
|
+
updated_at TEXT NOT NULL,
|
|
10777
|
+
components_json TEXT NOT NULL,
|
|
10778
|
+
PRIMARY KEY (file_hash, cli_version)
|
|
10779
|
+
);
|
|
10780
|
+
CREATE INDEX idx_extract_cache_file ON extract_cache(file_path);
|
|
10781
|
+
`);
|
|
10782
|
+
}
|
|
10783
|
+
const hasSelectCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='select_cache'`).all();
|
|
10784
|
+
if (hasSelectCache.length === 0) {
|
|
10785
|
+
db.exec(`
|
|
10786
|
+
CREATE TABLE select_cache (
|
|
10787
|
+
component_hash TEXT NOT NULL,
|
|
10788
|
+
prompt_hash TEXT NOT NULL,
|
|
10789
|
+
cli_version TEXT NOT NULL,
|
|
10790
|
+
decision TEXT NOT NULL CHECK (decision IN ('accepted','rejected')),
|
|
10791
|
+
reason TEXT,
|
|
10792
|
+
created_at TEXT NOT NULL,
|
|
10793
|
+
updated_at TEXT NOT NULL,
|
|
10794
|
+
PRIMARY KEY (component_hash, prompt_hash, cli_version)
|
|
10795
|
+
);
|
|
10796
|
+
`);
|
|
10797
|
+
}
|
|
10798
|
+
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='generation_cache'`).all();
|
|
10799
|
+
if (tables.length === 0) {
|
|
10800
|
+
db.exec(`
|
|
10801
|
+
CREATE TABLE generation_cache (
|
|
10802
|
+
input_hash TEXT NOT NULL,
|
|
10803
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10804
|
+
entity_id TEXT NOT NULL,
|
|
10805
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10806
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10807
|
+
created_at TEXT NOT NULL,
|
|
10808
|
+
updated_at TEXT NOT NULL,
|
|
10809
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
10810
|
+
);
|
|
10811
|
+
CREATE INDEX idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10812
|
+
CREATE INDEX idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10813
|
+
`);
|
|
10814
|
+
}
|
|
10815
|
+
const genCacheCols = db.prepare(`PRAGMA table_info(generation_cache)`).all();
|
|
10816
|
+
const hasPromptHash = genCacheCols.some((c2) => c2.name === "prompt_hash");
|
|
10817
|
+
const oldPkCols = genCacheCols.filter((c2) => c2.pk > 0).map((c2) => c2.name);
|
|
10818
|
+
const promptHashInPk = oldPkCols.includes("prompt_hash");
|
|
10819
|
+
if (!hasPromptHash) {
|
|
10820
|
+
db.exec(`ALTER TABLE generation_cache ADD COLUMN prompt_hash TEXT NOT NULL DEFAULT ''`);
|
|
10821
|
+
}
|
|
10822
|
+
if (!promptHashInPk) {
|
|
10823
|
+
db.exec("BEGIN");
|
|
10824
|
+
try {
|
|
10825
|
+
db.exec(`
|
|
10826
|
+
CREATE TABLE generation_cache__new (
|
|
10827
|
+
input_hash TEXT NOT NULL,
|
|
10828
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10829
|
+
entity_id TEXT NOT NULL,
|
|
10830
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10831
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10832
|
+
created_at TEXT NOT NULL,
|
|
10833
|
+
updated_at TEXT NOT NULL,
|
|
10834
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10835
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10836
|
+
);
|
|
10837
|
+
INSERT INTO generation_cache__new
|
|
10838
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10839
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10840
|
+
FROM generation_cache;
|
|
10841
|
+
DROP TABLE generation_cache;
|
|
10842
|
+
ALTER TABLE generation_cache__new RENAME TO generation_cache;
|
|
10843
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10844
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10845
|
+
`);
|
|
10846
|
+
db.exec("COMMIT");
|
|
10847
|
+
} catch (e) {
|
|
10848
|
+
db.exec("ROLLBACK");
|
|
10849
|
+
throw e;
|
|
10850
|
+
}
|
|
10851
|
+
}
|
|
10852
|
+
const genCacheTableSql = db.prepare(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'generation_cache'`).get();
|
|
10853
|
+
const hasTokenMappingEntityType = genCacheTableSql?.sql.includes("'token_mapping'") ?? true;
|
|
10854
|
+
if (!hasTokenMappingEntityType) {
|
|
10855
|
+
db.exec("BEGIN");
|
|
10856
|
+
try {
|
|
10857
|
+
db.exec(`
|
|
10858
|
+
CREATE TABLE generation_cache__new2 (
|
|
10859
|
+
input_hash TEXT NOT NULL,
|
|
10860
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10861
|
+
entity_id TEXT NOT NULL,
|
|
10862
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10863
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10864
|
+
created_at TEXT NOT NULL,
|
|
10865
|
+
updated_at TEXT NOT NULL,
|
|
10866
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10867
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10868
|
+
);
|
|
10869
|
+
INSERT INTO generation_cache__new2
|
|
10870
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10871
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10872
|
+
FROM generation_cache;
|
|
10873
|
+
DROP TABLE generation_cache;
|
|
10874
|
+
ALTER TABLE generation_cache__new2 RENAME TO generation_cache;
|
|
10875
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10876
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10877
|
+
`);
|
|
10878
|
+
db.exec("COMMIT");
|
|
10879
|
+
} catch (e) {
|
|
10880
|
+
db.exec("ROLLBACK");
|
|
10881
|
+
throw e;
|
|
10882
|
+
}
|
|
10883
|
+
}
|
|
10884
|
+
const hasCompositionCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='composition_cache'`).all();
|
|
10885
|
+
if (hasCompositionCache.length === 0) {
|
|
10886
|
+
db.exec(`
|
|
10887
|
+
CREATE TABLE composition_cache (
|
|
10888
|
+
input_hash TEXT NOT NULL,
|
|
10889
|
+
cli_version TEXT NOT NULL,
|
|
10890
|
+
agent_output TEXT NOT NULL,
|
|
10891
|
+
created_at TEXT NOT NULL,
|
|
10892
|
+
updated_at TEXT NOT NULL,
|
|
10893
|
+
PRIMARY KEY (input_hash, cli_version)
|
|
10894
|
+
);
|
|
10895
|
+
`);
|
|
10648
10896
|
}
|
|
10649
10897
|
}
|
|
10650
10898
|
function loadComponentReviewMetadata(db, sessionId2, componentName) {
|
|
@@ -11180,16 +11428,16 @@ function extractRelativeImportPaths(sourceText) {
|
|
|
11180
11428
|
return [...specifiers];
|
|
11181
11429
|
}
|
|
11182
11430
|
async function resolveRelativeImport(specifier, fromDir) {
|
|
11183
|
-
const basePath =
|
|
11431
|
+
const basePath = resolve9(fromDir, specifier);
|
|
11184
11432
|
const candidates = [
|
|
11185
11433
|
basePath,
|
|
11186
11434
|
...rewrittenSourcePaths(basePath),
|
|
11187
11435
|
...SIBLING_FILE_EXTENSIONS.map((ext) => `${basePath}${ext}`),
|
|
11188
|
-
...SIBLING_FILE_EXTENSIONS.map((ext) =>
|
|
11436
|
+
...SIBLING_FILE_EXTENSIONS.map((ext) => resolve9(basePath, `index${ext}`))
|
|
11189
11437
|
];
|
|
11190
11438
|
for (const candidate of candidates) {
|
|
11191
11439
|
try {
|
|
11192
|
-
await
|
|
11440
|
+
await readFile8(candidate, "utf8");
|
|
11193
11441
|
return candidate;
|
|
11194
11442
|
} catch {
|
|
11195
11443
|
}
|
|
@@ -11205,7 +11453,7 @@ async function resolveImportSpecifiers(sourceText, fromDir) {
|
|
|
11205
11453
|
return resolvedPaths;
|
|
11206
11454
|
}
|
|
11207
11455
|
async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateTypeNames = []) {
|
|
11208
|
-
const visited = /* @__PURE__ */ new Set([
|
|
11456
|
+
const visited = /* @__PURE__ */ new Set([resolve9(sourcePath)]);
|
|
11209
11457
|
const discovered = [];
|
|
11210
11458
|
let frontier = [{ text: sourceText, dir: dirname14(sourcePath) }];
|
|
11211
11459
|
for (let hop = 0; hop < MAX_SIBLING_DEPTH && discovered.length < MAX_SIBLING_CANDIDATES_EXPLORED; hop++) {
|
|
@@ -11219,7 +11467,7 @@ async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateType
|
|
|
11219
11467
|
if (discovered.length >= MAX_SIBLING_CANDIDATES_EXPLORED) break;
|
|
11220
11468
|
let content;
|
|
11221
11469
|
try {
|
|
11222
|
-
content = await
|
|
11470
|
+
content = await readFile8(resolvedPath, "utf8");
|
|
11223
11471
|
} catch {
|
|
11224
11472
|
continue;
|
|
11225
11473
|
}
|
|
@@ -11256,7 +11504,7 @@ async function loadComponentSourceRef(name, sourcePath, propNames = [], propType
|
|
|
11256
11504
|
let truncatedSiblingCount = 0;
|
|
11257
11505
|
const usesNotShown = /* @__PURE__ */ new Set();
|
|
11258
11506
|
try {
|
|
11259
|
-
const rawText = await
|
|
11507
|
+
const rawText = await readFile8(sourcePath, "utf8");
|
|
11260
11508
|
let siblingUsesNotShown;
|
|
11261
11509
|
let declaredTypeNames;
|
|
11262
11510
|
({
|
|
@@ -11692,6 +11940,108 @@ function backfillUnclassifiedProps(db, sessionId2) {
|
|
|
11692
11940
|
).run(sessionId2, sessionId2);
|
|
11693
11941
|
return Number(withCategory.changes) + Number(withoutCategory.changes);
|
|
11694
11942
|
}
|
|
11943
|
+
function computeMapTokensInputHash(db, sessionId2, componentSourceRefs = []) {
|
|
11944
|
+
const props = db.prepare(
|
|
11945
|
+
`SELECT rc.name AS component_name, rp.name AS prop_name, rp.cdf_token_kind, rp.default_value
|
|
11946
|
+
FROM raw_props rp
|
|
11947
|
+
JOIN raw_components rc ON rc.session_id = rp.session_id AND rc.component_id = rp.component_id
|
|
11948
|
+
WHERE rp.session_id = ? AND rp.cdf_type = 'token' AND rp.cdf_category = 'design'
|
|
11949
|
+
ORDER BY rc.name, rp.name`
|
|
11950
|
+
).all(sessionId2);
|
|
11951
|
+
const tokens = db.prepare(`SELECT path, type FROM raw_tokens WHERE session_id = ? ORDER BY path`).all(sessionId2);
|
|
11952
|
+
const defaultMappings = db.prepare("SELECT raw_name, path, source FROM raw_token_name_paths WHERE session_id = ? ORDER BY raw_name").all(sessionId2);
|
|
11953
|
+
const payload = {
|
|
11954
|
+
props: props.map((p) => ({
|
|
11955
|
+
component: p.component_name,
|
|
11956
|
+
prop: p.prop_name,
|
|
11957
|
+
tokenKind: p.cdf_token_kind,
|
|
11958
|
+
rawDefault: p.default_value
|
|
11959
|
+
})),
|
|
11960
|
+
tokens,
|
|
11961
|
+
defaultMappings,
|
|
11962
|
+
// The agent's evidence, not just its inputs: a comment or allowlist edit
|
|
11963
|
+
// in a source file (or a sibling it reads) changes the correct answer
|
|
11964
|
+
// without touching props or tokens, so it must invalidate the cache too.
|
|
11965
|
+
sourceRefs: [...componentSourceRefs].sort((a, b) => a.component.localeCompare(b.component)).map((ref) => ({
|
|
11966
|
+
component: ref.component,
|
|
11967
|
+
content: ref.content,
|
|
11968
|
+
siblingFiles: (ref.siblingFiles ?? []).map((s) => ({ path: s.path, content: s.content })).sort((a, b) => a.path.localeCompare(b.path)),
|
|
11969
|
+
usesNotShown: [...ref.usesNotShown ?? []].sort()
|
|
11970
|
+
}))
|
|
11971
|
+
};
|
|
11972
|
+
return createHash5("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
11973
|
+
}
|
|
11974
|
+
function lookupCache(db, inputHash, entityType, entityId, promptHash = "") {
|
|
11975
|
+
const row = db.prepare(
|
|
11976
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11977
|
+
FROM generation_cache
|
|
11978
|
+
WHERE input_hash = ? AND entity_type = ? AND entity_id = ? AND prompt_hash = ?`
|
|
11979
|
+
).get(inputHash, entityType, entityId, promptHash);
|
|
11980
|
+
if (!row) return null;
|
|
11981
|
+
return {
|
|
11982
|
+
inputHash: row.input_hash,
|
|
11983
|
+
entityType: row.entity_type,
|
|
11984
|
+
entityId: row.entity_id,
|
|
11985
|
+
sourceSessionId: row.source_session_id,
|
|
11986
|
+
humanEdited: row.human_edited === 1,
|
|
11987
|
+
promptHash: row.prompt_hash,
|
|
11988
|
+
createdAt: row.created_at,
|
|
11989
|
+
updatedAt: row.updated_at
|
|
11990
|
+
};
|
|
11991
|
+
}
|
|
11992
|
+
function lookupCacheByEntity(db, entityType, entityId) {
|
|
11993
|
+
const row = db.prepare(
|
|
11994
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11995
|
+
FROM generation_cache
|
|
11996
|
+
WHERE entity_type = ? AND entity_id = ?
|
|
11997
|
+
ORDER BY updated_at DESC LIMIT 1`
|
|
11998
|
+
).get(entityType, entityId);
|
|
11999
|
+
if (!row) return null;
|
|
12000
|
+
return {
|
|
12001
|
+
inputHash: row.input_hash,
|
|
12002
|
+
entityType: row.entity_type,
|
|
12003
|
+
entityId: row.entity_id,
|
|
12004
|
+
sourceSessionId: row.source_session_id,
|
|
12005
|
+
humanEdited: row.human_edited === 1,
|
|
12006
|
+
promptHash: row.prompt_hash,
|
|
12007
|
+
createdAt: row.created_at,
|
|
12008
|
+
updatedAt: row.updated_at
|
|
12009
|
+
};
|
|
12010
|
+
}
|
|
12011
|
+
function storeCache(db, inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash = "") {
|
|
12012
|
+
storeCaches(db, [{ inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash }]);
|
|
12013
|
+
}
|
|
12014
|
+
function storeCaches(db, entries) {
|
|
12015
|
+
if (entries.length === 0) return;
|
|
12016
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12017
|
+
const insert = db.prepare(
|
|
12018
|
+
`INSERT INTO generation_cache (input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
12019
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
12020
|
+
ON CONFLICT(input_hash, prompt_hash, entity_type, entity_id) DO UPDATE SET
|
|
12021
|
+
source_session_id = excluded.source_session_id,
|
|
12022
|
+
human_edited = CASE WHEN generation_cache.human_edited = 1 THEN 1 ELSE excluded.human_edited END,
|
|
12023
|
+
updated_at = excluded.updated_at`
|
|
12024
|
+
);
|
|
12025
|
+
db.exec("BEGIN");
|
|
12026
|
+
try {
|
|
12027
|
+
for (const entry of entries) {
|
|
12028
|
+
insert.run(
|
|
12029
|
+
entry.inputHash,
|
|
12030
|
+
entry.entityType,
|
|
12031
|
+
entry.entityId,
|
|
12032
|
+
entry.sourceSessionId,
|
|
12033
|
+
entry.humanEdited ? 1 : 0,
|
|
12034
|
+
now,
|
|
12035
|
+
now,
|
|
12036
|
+
entry.promptHash ?? ""
|
|
12037
|
+
);
|
|
12038
|
+
}
|
|
12039
|
+
db.exec("COMMIT");
|
|
12040
|
+
} catch (e) {
|
|
12041
|
+
db.exec("ROLLBACK");
|
|
12042
|
+
throw e;
|
|
12043
|
+
}
|
|
12044
|
+
}
|
|
11695
12045
|
function storeScannedFiles(db, sessionId2, filePaths) {
|
|
11696
12046
|
db.exec("BEGIN");
|
|
11697
12047
|
try {
|
|
@@ -11774,7 +12124,105 @@ function filterUnknownSlotAllowedComponents(db, sessionId2, allowedComponentName
|
|
|
11774
12124
|
}
|
|
11775
12125
|
return unknown;
|
|
11776
12126
|
}
|
|
11777
|
-
function
|
|
12127
|
+
function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentId, manageTransaction = true, options = {}) {
|
|
12128
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12129
|
+
if (manageTransaction) db.exec("BEGIN");
|
|
12130
|
+
try {
|
|
12131
|
+
const srcComp = db.prepare(
|
|
12132
|
+
`SELECT description, status, component_description_rationale, props_rationale, slots_rationale
|
|
12133
|
+
FROM raw_components WHERE session_id = ? AND component_id = ?`
|
|
12134
|
+
).get(sourceSessionId, componentId);
|
|
12135
|
+
if (srcComp) {
|
|
12136
|
+
db.prepare(
|
|
12137
|
+
`UPDATE raw_components
|
|
12138
|
+
SET description = ?, status = ?, component_description_rationale = ?, props_rationale = ?, slots_rationale = ?, extracted_at = ?
|
|
12139
|
+
WHERE session_id = ? AND component_id = ?`
|
|
12140
|
+
).run(
|
|
12141
|
+
srcComp.description,
|
|
12142
|
+
srcComp.status,
|
|
12143
|
+
srcComp.component_description_rationale,
|
|
12144
|
+
srcComp.props_rationale,
|
|
12145
|
+
srcComp.slots_rationale,
|
|
12146
|
+
now,
|
|
12147
|
+
targetSessionId,
|
|
12148
|
+
componentId
|
|
12149
|
+
);
|
|
12150
|
+
}
|
|
12151
|
+
const srcProps = db.prepare(
|
|
12152
|
+
`SELECT name, cdf_type, cdf_category, cdf_token_kind, required, description, default_value, rationale
|
|
12153
|
+
FROM raw_props WHERE session_id = ? AND component_id = ?`
|
|
12154
|
+
).all(sourceSessionId, componentId);
|
|
12155
|
+
for (const p of srcProps) {
|
|
12156
|
+
db.prepare(
|
|
12157
|
+
`UPDATE raw_props SET cdf_type = ?, cdf_category = ?, cdf_token_kind = ?, required = ?, description = ?, default_value = ?, rationale = ?
|
|
12158
|
+
WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12159
|
+
).run(
|
|
12160
|
+
p.cdf_type,
|
|
12161
|
+
p.cdf_category,
|
|
12162
|
+
p.cdf_token_kind,
|
|
12163
|
+
p.required,
|
|
12164
|
+
p.description,
|
|
12165
|
+
p.default_value,
|
|
12166
|
+
p.rationale,
|
|
12167
|
+
targetSessionId,
|
|
12168
|
+
componentId,
|
|
12169
|
+
p.name
|
|
12170
|
+
);
|
|
12171
|
+
}
|
|
12172
|
+
db.prepare(`DELETE FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`).run(
|
|
12173
|
+
targetSessionId,
|
|
12174
|
+
componentId
|
|
12175
|
+
);
|
|
12176
|
+
const srcAV = db.prepare(
|
|
12177
|
+
`SELECT prop_name, position, value FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`
|
|
12178
|
+
).all(sourceSessionId, componentId);
|
|
12179
|
+
const insertAV = db.prepare(
|
|
12180
|
+
`INSERT INTO raw_prop_allowed_values (session_id, component_id, prop_name, position, value) VALUES (?, ?, ?, ?, ?)`
|
|
12181
|
+
);
|
|
12182
|
+
for (const av of srcAV) {
|
|
12183
|
+
insertAV.run(targetSessionId, componentId, av.prop_name, av.position, av.value);
|
|
12184
|
+
}
|
|
12185
|
+
const srcSlots = db.prepare(`SELECT name, required, description, rationale FROM raw_slots WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
|
|
12186
|
+
for (const s of srcSlots) {
|
|
12187
|
+
db.prepare(
|
|
12188
|
+
`UPDATE raw_slots SET required = ?, description = ?, rationale = ? WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12189
|
+
).run(s.required, s.description, s.rationale, targetSessionId, componentId, s.name);
|
|
12190
|
+
}
|
|
12191
|
+
db.prepare(`DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`).run(
|
|
12192
|
+
targetSessionId,
|
|
12193
|
+
componentId
|
|
12194
|
+
);
|
|
12195
|
+
const srcSAC = db.prepare(
|
|
12196
|
+
`SELECT slot_name, position, allowed_component FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`
|
|
12197
|
+
).all(sourceSessionId, componentId);
|
|
12198
|
+
const insertSAC = db.prepare(
|
|
12199
|
+
`INSERT INTO raw_slot_allowed_components (session_id, component_id, slot_name, allowed_component, position) VALUES (?, ?, ?, ?, ?)`
|
|
12200
|
+
);
|
|
12201
|
+
const allowedSAC = options.allowedComponentNames ? srcSAC.filter((sac) => options.allowedComponentNames.has(sac.allowed_component)) : srcSAC;
|
|
12202
|
+
for (const sac of allowedSAC) {
|
|
12203
|
+
insertSAC.run(targetSessionId, componentId, sac.slot_name, sac.allowed_component, sac.position);
|
|
12204
|
+
}
|
|
12205
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12206
|
+
if (manageTransaction) db.exec("COMMIT");
|
|
12207
|
+
} catch (e) {
|
|
12208
|
+
if (manageTransaction) db.exec("ROLLBACK");
|
|
12209
|
+
throw e;
|
|
12210
|
+
}
|
|
12211
|
+
}
|
|
12212
|
+
function copyComponentsFromCache(db, entries, options = {}) {
|
|
12213
|
+
if (entries.length === 0) return;
|
|
12214
|
+
db.exec("BEGIN");
|
|
12215
|
+
try {
|
|
12216
|
+
for (const entry of entries) {
|
|
12217
|
+
copyComponentFromCache(db, entry.sourceSessionId, entry.targetSessionId, entry.componentId, false, options);
|
|
12218
|
+
}
|
|
12219
|
+
db.exec("COMMIT");
|
|
12220
|
+
} catch (e) {
|
|
12221
|
+
db.exec("ROLLBACK");
|
|
12222
|
+
throw e;
|
|
12223
|
+
}
|
|
12224
|
+
}
|
|
12225
|
+
function copyTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
11778
12226
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11779
12227
|
db.exec("BEGIN");
|
|
11780
12228
|
try {
|
|
@@ -11795,7 +12243,139 @@ function copyTokensBetweenSessions(db, sourceSessionId, targetSessionId) {
|
|
|
11795
12243
|
throw e;
|
|
11796
12244
|
}
|
|
11797
12245
|
}
|
|
11798
|
-
|
|
12246
|
+
function copyMapTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
12247
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12248
|
+
let copiedCount = 0;
|
|
12249
|
+
db.exec("BEGIN");
|
|
12250
|
+
try {
|
|
12251
|
+
const sourceRows = db.prepare(
|
|
12252
|
+
`SELECT rc.name AS component_name, rptp.prop_name, rptp.source, rptp.position, rptp.path
|
|
12253
|
+
FROM raw_prop_token_paths rptp
|
|
12254
|
+
JOIN raw_components rc ON rc.session_id = rptp.session_id AND rc.component_id = rptp.component_id
|
|
12255
|
+
WHERE rptp.session_id = ?
|
|
12256
|
+
ORDER BY rc.name, rptp.prop_name, rptp.position`
|
|
12257
|
+
).all(sourceSessionId);
|
|
12258
|
+
const targetComponents = db.prepare(`SELECT component_id, name FROM raw_components WHERE session_id = ?`).all(targetSessionId);
|
|
12259
|
+
const targetIdByName = new Map(targetComponents.map((c2) => [c2.name, c2.component_id]));
|
|
12260
|
+
const targetProps = new Set(
|
|
12261
|
+
db.prepare(`SELECT component_id, name FROM raw_props WHERE session_id = ?`).all(targetSessionId).map((p) => `${p.component_id}::${p.name}`)
|
|
12262
|
+
);
|
|
12263
|
+
const insertPath = db.prepare(
|
|
12264
|
+
`INSERT INTO raw_prop_token_paths (session_id, component_id, prop_name, source, position, path)
|
|
12265
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
12266
|
+
);
|
|
12267
|
+
const clearedProps = /* @__PURE__ */ new Set();
|
|
12268
|
+
const copiedProps = /* @__PURE__ */ new Set();
|
|
12269
|
+
for (const row of sourceRows) {
|
|
12270
|
+
const targetComponentId = targetIdByName.get(row.component_name);
|
|
12271
|
+
if (!targetComponentId) continue;
|
|
12272
|
+
if (!targetProps.has(`${targetComponentId}::${row.prop_name}`)) continue;
|
|
12273
|
+
const propKey = `${targetComponentId}::${row.prop_name}`;
|
|
12274
|
+
if (!clearedProps.has(propKey)) {
|
|
12275
|
+
clearedProps.add(propKey);
|
|
12276
|
+
db.prepare(`DELETE FROM raw_prop_token_paths WHERE session_id = ? AND component_id = ? AND prop_name = ?`).run(
|
|
12277
|
+
targetSessionId,
|
|
12278
|
+
targetComponentId,
|
|
12279
|
+
row.prop_name
|
|
12280
|
+
);
|
|
12281
|
+
}
|
|
12282
|
+
insertPath.run(targetSessionId, targetComponentId, row.prop_name, row.source, row.position, row.path);
|
|
12283
|
+
copiedProps.add(propKey);
|
|
12284
|
+
}
|
|
12285
|
+
copiedCount = copiedProps.size;
|
|
12286
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12287
|
+
db.exec("COMMIT");
|
|
12288
|
+
} catch (e) {
|
|
12289
|
+
db.exec("ROLLBACK");
|
|
12290
|
+
throw e;
|
|
12291
|
+
}
|
|
12292
|
+
return copiedCount;
|
|
12293
|
+
}
|
|
12294
|
+
async function getCliCacheVersion() {
|
|
12295
|
+
if (_cliCacheVersionCache) return _cliCacheVersionCache;
|
|
12296
|
+
try {
|
|
12297
|
+
const { hashContent: hashContent2 } = await Promise.resolve().then(() => (init_cache_keys(), cache_keys_exports));
|
|
12298
|
+
const { resolveSkillPath: resolveSkillPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
12299
|
+
const skills = ["components", "tokens", "select"];
|
|
12300
|
+
const parts = [];
|
|
12301
|
+
for (const s of skills) {
|
|
12302
|
+
try {
|
|
12303
|
+
const p = resolveSkillPath2(s);
|
|
12304
|
+
parts.push(readFileSync5(p, "utf8"));
|
|
12305
|
+
} catch {
|
|
12306
|
+
parts.push(`<missing:${s}>`);
|
|
12307
|
+
}
|
|
12308
|
+
}
|
|
12309
|
+
_cliCacheVersionCache = hashContent2(parts.join("\n---\n"));
|
|
12310
|
+
return _cliCacheVersionCache;
|
|
12311
|
+
} catch {
|
|
12312
|
+
_cliCacheVersionCache = "fallback";
|
|
12313
|
+
return _cliCacheVersionCache;
|
|
12314
|
+
}
|
|
12315
|
+
}
|
|
12316
|
+
function storeExtractCache(db, filePath, fileHash, cliVersion2, components) {
|
|
12317
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12318
|
+
const componentsJson = JSON.stringify(components);
|
|
12319
|
+
db.prepare(
|
|
12320
|
+
`INSERT INTO extract_cache (file_path, file_hash, cli_version, created_at, updated_at, components_json)
|
|
12321
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
12322
|
+
ON CONFLICT(file_hash, cli_version) DO UPDATE SET
|
|
12323
|
+
file_path = excluded.file_path,
|
|
12324
|
+
updated_at = excluded.updated_at,
|
|
12325
|
+
components_json = excluded.components_json`
|
|
12326
|
+
).run(filePath, fileHash, cliVersion2, now, now, componentsJson);
|
|
12327
|
+
}
|
|
12328
|
+
function lookupExtractCache(db, fileHash, cliVersion2) {
|
|
12329
|
+
const row = db.prepare(
|
|
12330
|
+
`SELECT file_path, file_hash, cli_version, created_at, updated_at, components_json
|
|
12331
|
+
FROM extract_cache
|
|
12332
|
+
WHERE file_hash = ? AND cli_version = ?`
|
|
12333
|
+
).get(fileHash, cliVersion2);
|
|
12334
|
+
if (!row) return null;
|
|
12335
|
+
let components = [];
|
|
12336
|
+
try {
|
|
12337
|
+
components = JSON.parse(row.components_json);
|
|
12338
|
+
} catch {
|
|
12339
|
+
return null;
|
|
12340
|
+
}
|
|
12341
|
+
return {
|
|
12342
|
+
filePath: row.file_path,
|
|
12343
|
+
fileHash: row.file_hash,
|
|
12344
|
+
cliVersion: row.cli_version,
|
|
12345
|
+
createdAt: row.created_at,
|
|
12346
|
+
updatedAt: row.updated_at,
|
|
12347
|
+
components
|
|
12348
|
+
};
|
|
12349
|
+
}
|
|
12350
|
+
function storeSelectCache(db, componentHash, promptHash, cliVersion2, decision, reason) {
|
|
12351
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12352
|
+
db.prepare(
|
|
12353
|
+
`INSERT INTO select_cache (component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at)
|
|
12354
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
12355
|
+
ON CONFLICT(component_hash, prompt_hash, cli_version) DO UPDATE SET
|
|
12356
|
+
decision = excluded.decision,
|
|
12357
|
+
reason = excluded.reason,
|
|
12358
|
+
updated_at = excluded.updated_at`
|
|
12359
|
+
).run(componentHash, promptHash, cliVersion2, decision, reason, now, now);
|
|
12360
|
+
}
|
|
12361
|
+
function lookupSelectCache(db, componentHash, promptHash, cliVersion2) {
|
|
12362
|
+
const row = db.prepare(
|
|
12363
|
+
`SELECT component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at
|
|
12364
|
+
FROM select_cache
|
|
12365
|
+
WHERE component_hash = ? AND prompt_hash = ? AND cli_version = ?`
|
|
12366
|
+
).get(componentHash, promptHash, cliVersion2);
|
|
12367
|
+
if (!row) return null;
|
|
12368
|
+
return {
|
|
12369
|
+
componentHash: row.component_hash,
|
|
12370
|
+
promptHash: row.prompt_hash,
|
|
12371
|
+
cliVersion: row.cli_version,
|
|
12372
|
+
decision: row.decision,
|
|
12373
|
+
reason: row.reason,
|
|
12374
|
+
createdAt: row.created_at,
|
|
12375
|
+
updatedAt: row.updated_at
|
|
12376
|
+
};
|
|
12377
|
+
}
|
|
12378
|
+
var SCHEMA, MAX_COMPONENT_SOURCE_CHARS, MAX_SIBLING_FILES, MAX_SIBLING_SNIPPET_CHARS, MAX_TYPE_DECLARING_SIBLING_CHARS, MAX_ENLARGED_SIBLINGS, MAX_SIBLING_DEPTH, MAX_SIBLING_CANDIDATES_EXPLORED, RELATIVE_IMPORT_PATTERN, SIBLING_FILE_EXTENSIONS, TS_ESM_EXTENSION_REWRITES, IDENTIFIER_PATTERN, _cliCacheVersionCache;
|
|
11799
12379
|
var init_db = __esm({
|
|
11800
12380
|
"packages/experience-design-system-cli-legacy/src/session/db.ts"() {
|
|
11801
12381
|
"use strict";
|
|
@@ -11809,6 +12389,8 @@ var init_db = __esm({
|
|
|
11809
12389
|
init_write2();
|
|
11810
12390
|
init_session_resolver();
|
|
11811
12391
|
init_read3();
|
|
12392
|
+
init_hash_component_shape();
|
|
12393
|
+
init_hash_token_content();
|
|
11812
12394
|
init_read3();
|
|
11813
12395
|
init_store_dtcg_tokens();
|
|
11814
12396
|
init_apply_tool_calls();
|
|
@@ -11932,6 +12514,17 @@ CREATE TABLE IF NOT EXISTS raw_tokens (
|
|
|
11932
12514
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
11933
12515
|
);
|
|
11934
12516
|
|
|
12517
|
+
CREATE TABLE IF NOT EXISTS generation_cache (
|
|
12518
|
+
input_hash TEXT NOT NULL,
|
|
12519
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
12520
|
+
entity_id TEXT NOT NULL,
|
|
12521
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
12522
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
12523
|
+
created_at TEXT NOT NULL,
|
|
12524
|
+
updated_at TEXT NOT NULL,
|
|
12525
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
12526
|
+
);
|
|
12527
|
+
|
|
11935
12528
|
CREATE TABLE IF NOT EXISTS scanned_files (
|
|
11936
12529
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
11937
12530
|
path TEXT NOT NULL,
|
|
@@ -11977,9 +12570,10 @@ CREATE INDEX IF NOT EXISTS idx_raw_props_session ON raw_props(session_id,
|
|
|
11977
12570
|
CREATE INDEX IF NOT EXISTS idx_raw_slots_session ON raw_slots(session_id, component_id);
|
|
11978
12571
|
CREATE INDEX IF NOT EXISTS idx_raw_tokens_session ON raw_tokens(session_id);
|
|
11979
12572
|
CREATE INDEX IF NOT EXISTS idx_raw_token_groups_session ON raw_token_groups(session_id);
|
|
12573
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
12574
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
11980
12575
|
CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session_id);
|
|
11981
12576
|
`;
|
|
11982
|
-
REMOVED_CACHE_TABLES = ["generation_cache", "extract_cache", "composition_cache", "select_cache"];
|
|
11983
12577
|
MAX_COMPONENT_SOURCE_CHARS = 8e3;
|
|
11984
12578
|
MAX_SIBLING_FILES = 5;
|
|
11985
12579
|
MAX_SIBLING_SNIPPET_CHARS = 1200;
|
|
@@ -11996,15 +12590,16 @@ CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session
|
|
|
11996
12590
|
[".cjs", [".cts", ".cjs"]]
|
|
11997
12591
|
];
|
|
11998
12592
|
IDENTIFIER_PATTERN = /[A-Za-z_$][A-Za-z0-9_$]*/g;
|
|
12593
|
+
_cliCacheVersionCache = null;
|
|
11999
12594
|
}
|
|
12000
12595
|
});
|
|
12001
12596
|
|
|
12002
12597
|
// packages/experience-design-system-cli-legacy/src/helpers/read-existing-contentful-entities-from-session.ts
|
|
12003
|
-
import { readFile as
|
|
12598
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
12004
12599
|
async function readExistingContentfulEntitiesFromSession(path) {
|
|
12005
12600
|
if (!path) return void 0;
|
|
12006
12601
|
try {
|
|
12007
|
-
const raw = await
|
|
12602
|
+
const raw = await readFile9(path, "utf8");
|
|
12008
12603
|
const parsed = JSON.parse(raw);
|
|
12009
12604
|
if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens)) return void 0;
|
|
12010
12605
|
return parsed;
|
|
@@ -12128,21 +12723,21 @@ var init_resolve_session_id = __esm({
|
|
|
12128
12723
|
});
|
|
12129
12724
|
|
|
12130
12725
|
// packages/experience-design-system-cli-legacy/src/analyze/select/persistence.ts
|
|
12131
|
-
import { access, appendFile, mkdir as mkdir2, readFile as
|
|
12726
|
+
import { access, appendFile, mkdir as mkdir2, readFile as readFile10, writeFile as writeFile2 } from "node:fs/promises";
|
|
12132
12727
|
import { homedir as homedir4 } from "node:os";
|
|
12133
|
-
import { resolve as
|
|
12728
|
+
import { resolve as resolve10 } from "node:path";
|
|
12134
12729
|
function getRefineArtifactsRoot() {
|
|
12135
12730
|
if (process.env.EDS_REVIEW_ARTIFACTS_DIR) {
|
|
12136
|
-
return
|
|
12731
|
+
return resolve10(process.env.EDS_REVIEW_ARTIFACTS_DIR);
|
|
12137
12732
|
}
|
|
12138
|
-
return
|
|
12733
|
+
return resolve10(homedir4(), ".contentful", "experience-design-system-cli", "reviews");
|
|
12139
12734
|
}
|
|
12140
12735
|
async function getRefineSessionPaths(sessionId2, artifactsRoot) {
|
|
12141
|
-
const sessionDir =
|
|
12736
|
+
const sessionDir = resolve10(artifactsRoot, sessionId2);
|
|
12142
12737
|
return {
|
|
12143
12738
|
sessionDir,
|
|
12144
|
-
eventsPath:
|
|
12145
|
-
statePath:
|
|
12739
|
+
eventsPath: resolve10(sessionDir, "events.jsonl"),
|
|
12740
|
+
statePath: resolve10(sessionDir, "current-review-state.json")
|
|
12146
12741
|
};
|
|
12147
12742
|
}
|
|
12148
12743
|
async function saveReviewState(statePath, session) {
|
|
@@ -12153,7 +12748,7 @@ async function ensureRefineSession(sessionId2, artifactsRoot, initialSnapshot) {
|
|
|
12153
12748
|
await mkdir2(paths.sessionDir, { recursive: true });
|
|
12154
12749
|
try {
|
|
12155
12750
|
await access(paths.statePath);
|
|
12156
|
-
const savedState = await
|
|
12751
|
+
const savedState = await readFile10(paths.statePath, "utf8");
|
|
12157
12752
|
return JSON.parse(savedState);
|
|
12158
12753
|
} catch {
|
|
12159
12754
|
await writeFile2(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
|
|
@@ -12638,8 +13233,8 @@ var init_path_exists = __esm({
|
|
|
12638
13233
|
});
|
|
12639
13234
|
|
|
12640
13235
|
// packages/experience-design-system-cli-legacy/src/lib/prompt-overrides.ts
|
|
12641
|
-
import { readFile as
|
|
12642
|
-
import { resolve as
|
|
13236
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
13237
|
+
import { resolve as resolve11 } from "node:path";
|
|
12643
13238
|
function looksLikePath(value) {
|
|
12644
13239
|
if (value.includes("/") || value.includes("\\")) return true;
|
|
12645
13240
|
if (value.startsWith("~")) return true;
|
|
@@ -12671,9 +13266,9 @@ function parsePromptOverrides(inputs) {
|
|
|
12671
13266
|
}
|
|
12672
13267
|
async function resolvePromptOverride(override) {
|
|
12673
13268
|
if (override.kind === "text") return override.value;
|
|
12674
|
-
const abs =
|
|
13269
|
+
const abs = resolve11(override.value);
|
|
12675
13270
|
try {
|
|
12676
|
-
return await
|
|
13271
|
+
return await readFile11(abs, "utf8");
|
|
12677
13272
|
} catch {
|
|
12678
13273
|
throw new Error(`--prompt: could not read prompt file: ${abs}`);
|
|
12679
13274
|
}
|
|
@@ -12688,21 +13283,21 @@ var init_prompt_overrides = __esm({
|
|
|
12688
13283
|
|
|
12689
13284
|
// packages/experience-design-system-cli-legacy/src/generate/command.ts
|
|
12690
13285
|
import { createElement } from "react";
|
|
12691
|
-
import { readFile as
|
|
12692
|
-
import { join as join14, resolve as
|
|
13286
|
+
import { readFile as readFile12, readdir, stat } from "node:fs/promises";
|
|
13287
|
+
import { join as join14, resolve as resolve12 } from "node:path";
|
|
12693
13288
|
async function assertFileExists(flag, p) {
|
|
12694
13289
|
if (!await pathExists(p)) die(`Error: file not found: ${p} (from ${flag})`);
|
|
12695
13290
|
}
|
|
12696
13291
|
async function readFileInline(path) {
|
|
12697
13292
|
if (!path) return void 0;
|
|
12698
|
-
const resolved =
|
|
13293
|
+
const resolved = resolve12(path);
|
|
12699
13294
|
let s;
|
|
12700
13295
|
try {
|
|
12701
13296
|
s = await stat(resolved);
|
|
12702
13297
|
} catch {
|
|
12703
13298
|
return void 0;
|
|
12704
13299
|
}
|
|
12705
|
-
if (!s.isDirectory()) return
|
|
13300
|
+
if (!s.isDirectory()) return readFile12(resolved, "utf8");
|
|
12706
13301
|
const files = [];
|
|
12707
13302
|
async function walk(dir) {
|
|
12708
13303
|
let entries;
|
|
@@ -12728,7 +13323,7 @@ async function readFileInline(path) {
|
|
|
12728
13323
|
}
|
|
12729
13324
|
await walk(resolved);
|
|
12730
13325
|
if (files.length === 0) return void 0;
|
|
12731
|
-
const parts = await Promise.all(files.map((f) =>
|
|
13326
|
+
const parts = await Promise.all(files.map((f) => readFile12(f, "utf8").catch(() => "")));
|
|
12732
13327
|
return parts.filter(Boolean).join("\n\n");
|
|
12733
13328
|
}
|
|
12734
13329
|
function printFallbackInstructions(options) {
|
|
@@ -12753,6 +13348,23 @@ function printFallbackInstructions(options) {
|
|
|
12753
13348
|
function generatePropBuckets(component) {
|
|
12754
13349
|
return logPropBuckets("generate", [bucketComponentProps(component)]);
|
|
12755
13350
|
}
|
|
13351
|
+
function createCachedComponentResult(componentName, warnings = []) {
|
|
13352
|
+
return {
|
|
13353
|
+
componentName,
|
|
13354
|
+
classified: 0,
|
|
13355
|
+
excluded: 0,
|
|
13356
|
+
slots: 0,
|
|
13357
|
+
warnings,
|
|
13358
|
+
failed: false,
|
|
13359
|
+
cached: true,
|
|
13360
|
+
renamedSlotsCount: 0
|
|
13361
|
+
};
|
|
13362
|
+
}
|
|
13363
|
+
function writeCachedComponentStatus(position, componentName, pinned) {
|
|
13364
|
+
const status = pinned ? c.cyan("pinned (human-edited)") : c.green("cached");
|
|
13365
|
+
process.stderr.write(` ${position} ${c.bold(componentName)} ${status}
|
|
13366
|
+
`);
|
|
13367
|
+
}
|
|
12756
13368
|
async function showGenerateView(result) {
|
|
12757
13369
|
if (process.stdout.isTTY) {
|
|
12758
13370
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -12773,6 +13385,29 @@ session=${result.sessionId}
|
|
|
12773
13385
|
);
|
|
12774
13386
|
await exitWithAnalytics(0);
|
|
12775
13387
|
}
|
|
13388
|
+
function normalizeComponentForCache(component) {
|
|
13389
|
+
const slots = component.slots.map((slot, index, allSlots) => ({
|
|
13390
|
+
...slot,
|
|
13391
|
+
name: slot.name.trim() || (allSlots.length === 1 ? "children" : `slot_${index}`)
|
|
13392
|
+
}));
|
|
13393
|
+
return { ...component, slots };
|
|
13394
|
+
}
|
|
13395
|
+
function lookupComponentCache(db, component, promptHash) {
|
|
13396
|
+
const normalized = normalizeComponentForCache(component);
|
|
13397
|
+
const inputHash = hashComponentShape(normalized);
|
|
13398
|
+
const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
|
|
13399
|
+
if (cached) return cached;
|
|
13400
|
+
const legacyInputHash = hashComponentShape(component);
|
|
13401
|
+
return legacyInputHash === inputHash ? null : lookupCache(db, legacyInputHash, "component", component.component_id, promptHash);
|
|
13402
|
+
}
|
|
13403
|
+
function resolveComponentCache(db, component, promptHash, allowedComponentNames2) {
|
|
13404
|
+
const cached = lookupComponentCache(db, component, promptHash);
|
|
13405
|
+
if (cached && findUnknownSlotAllowedComponents(db, cached.sourceSessionId, allowedComponentNames2, component.component_id).length === 0) {
|
|
13406
|
+
return { entry: cached, humanEdited: cached.humanEdited };
|
|
13407
|
+
}
|
|
13408
|
+
const pinned = lookupCacheByEntity(db, "component", component.component_id);
|
|
13409
|
+
return pinned?.humanEdited && findUnknownSlotAllowedComponents(db, pinned.sourceSessionId, allowedComponentNames2, component.component_id).length === 0 ? { entry: pinned, humanEdited: true } : null;
|
|
13410
|
+
}
|
|
12776
13411
|
async function runOneComponent(options, component, index, total) {
|
|
12777
13412
|
const {
|
|
12778
13413
|
agent,
|
|
@@ -12782,10 +13417,13 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12782
13417
|
tokensInline,
|
|
12783
13418
|
tokenMapInline,
|
|
12784
13419
|
verbose,
|
|
13420
|
+
noCache,
|
|
12785
13421
|
skillPathOverride,
|
|
12786
13422
|
skillContentOverride,
|
|
13423
|
+
promptHash,
|
|
12787
13424
|
existingContentfulEntities,
|
|
12788
13425
|
existingTokensInline,
|
|
13426
|
+
precomputedCachedNames,
|
|
12789
13427
|
allowedComponentNames: allowedComponentNames2
|
|
12790
13428
|
} = options;
|
|
12791
13429
|
const pos = c.dim(`[${index + 1}/${total}]`);
|
|
@@ -12810,6 +13448,40 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12810
13448
|
allowedComponents: slot.allowedComponents.filter((name) => allowedComponentNames2.has(name))
|
|
12811
13449
|
};
|
|
12812
13450
|
});
|
|
13451
|
+
const cacheComponent = normalizeComponentForCache(component);
|
|
13452
|
+
if (!noCache && precomputedCachedNames.has(component.name)) {
|
|
13453
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13454
|
+
return createCachedComponentResult(component.name);
|
|
13455
|
+
}
|
|
13456
|
+
if (!noCache) {
|
|
13457
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13458
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13459
|
+
if (resolution && !resolution.humanEdited) {
|
|
13460
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13461
|
+
allowedComponentNames: allowedComponentNames2
|
|
13462
|
+
});
|
|
13463
|
+
storeCache(
|
|
13464
|
+
db,
|
|
13465
|
+
inputHash,
|
|
13466
|
+
"component",
|
|
13467
|
+
component.component_id,
|
|
13468
|
+
resolution.entry.sourceSessionId,
|
|
13469
|
+
resolution.entry.humanEdited,
|
|
13470
|
+
promptHash
|
|
13471
|
+
);
|
|
13472
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13473
|
+
return createCachedComponentResult(component.name);
|
|
13474
|
+
}
|
|
13475
|
+
if (resolution?.humanEdited) {
|
|
13476
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13477
|
+
allowedComponentNames: allowedComponentNames2
|
|
13478
|
+
});
|
|
13479
|
+
writeCachedComponentStatus(pos, component.name, true);
|
|
13480
|
+
return createCachedComponentResult(`${component.name}`, [
|
|
13481
|
+
`${component.name}: source changed but human edits preserved`
|
|
13482
|
+
]);
|
|
13483
|
+
}
|
|
13484
|
+
}
|
|
12813
13485
|
const rawComponentsInline = JSON.stringify(
|
|
12814
13486
|
[
|
|
12815
13487
|
{
|
|
@@ -12882,6 +13554,10 @@ ${outputBuf}`);
|
|
|
12882
13554
|
const applied = applyToolCalls(db, sessionId2, component.component_id, component.name, calls, warnings, {
|
|
12883
13555
|
allowedComponentNames: allowedComponentNames2
|
|
12884
13556
|
});
|
|
13557
|
+
if (!noCache) {
|
|
13558
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13559
|
+
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
13560
|
+
}
|
|
12885
13561
|
return {
|
|
12886
13562
|
componentName: component.name,
|
|
12887
13563
|
classified: applied.classified,
|
|
@@ -12933,7 +13609,7 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12933
13609
|
try {
|
|
12934
13610
|
const artifactsRoot = getRefineArtifactsRoot();
|
|
12935
13611
|
const paths = await getRefineSessionPaths(sessionId2, artifactsRoot);
|
|
12936
|
-
const raw = await
|
|
13612
|
+
const raw = await readFile12(paths.statePath, "utf8");
|
|
12937
13613
|
const snapshot = JSON.parse(raw);
|
|
12938
13614
|
const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
|
|
12939
13615
|
if (accepted.length === 0) return null;
|
|
@@ -12942,6 +13618,15 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12942
13618
|
return null;
|
|
12943
13619
|
}
|
|
12944
13620
|
}
|
|
13621
|
+
function parsePrecomputedCachedNames(value) {
|
|
13622
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
13623
|
+
try {
|
|
13624
|
+
const parsed = JSON.parse(value);
|
|
13625
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((name) => typeof name === "string") : []);
|
|
13626
|
+
} catch {
|
|
13627
|
+
return /* @__PURE__ */ new Set();
|
|
13628
|
+
}
|
|
13629
|
+
}
|
|
12945
13630
|
async function runGenerateSkill(skill, opts, verbose = false) {
|
|
12946
13631
|
const savedCreds = await readExperiencesCredentials();
|
|
12947
13632
|
const agentName = opts.agent ?? savedCreds.agent;
|
|
@@ -12970,8 +13655,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12970
13655
|
}
|
|
12971
13656
|
const generatePromptPath = generatePrompt === void 0 ? configuredGeneratePromptPath : void 0;
|
|
12972
13657
|
if (generatePromptPath) {
|
|
12973
|
-
if (!await pathExists(
|
|
12974
|
-
die(`Error: custom prompt path not found: ${
|
|
13658
|
+
if (!await pathExists(resolve12(generatePromptPath))) {
|
|
13659
|
+
die(`Error: custom prompt path not found: ${resolve12(generatePromptPath)}`);
|
|
12975
13660
|
}
|
|
12976
13661
|
if (!generatePromptPath.toLowerCase().endsWith(".md")) {
|
|
12977
13662
|
process.stderr.write(
|
|
@@ -12979,7 +13664,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12979
13664
|
`
|
|
12980
13665
|
);
|
|
12981
13666
|
}
|
|
12982
|
-
process.stderr.write(formatCustomPromptBanner("components",
|
|
13667
|
+
process.stderr.write(formatCustomPromptBanner("components", resolve12(generatePromptPath)));
|
|
12983
13668
|
}
|
|
12984
13669
|
if (skill === "tokens" && !opts.rawTokens) {
|
|
12985
13670
|
die("Error: --raw-tokens is required when using generate tokens");
|
|
@@ -12995,7 +13680,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12995
13680
|
let existingContentfulEntities;
|
|
12996
13681
|
let existingTokensInline;
|
|
12997
13682
|
if (opts.existingEntitiesPath) {
|
|
12998
|
-
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
13683
|
+
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(resolve12(opts.existingEntitiesPath));
|
|
12999
13684
|
if (existingContentfulEntities) {
|
|
13000
13685
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
13001
13686
|
} else {
|
|
@@ -13094,7 +13779,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13094
13779
|
rawComponentsInline: sampleInline ?? rawTokensInline,
|
|
13095
13780
|
propBucketsInline: sampleComponent ? generatePropBuckets(sampleComponent) : void 0,
|
|
13096
13781
|
rawTokensInline: skill === "tokens" ? rawTokensInline : void 0,
|
|
13097
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13782
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13098
13783
|
tokensInline,
|
|
13099
13784
|
tokenMapInline,
|
|
13100
13785
|
outDir: process.cwd(),
|
|
@@ -13120,7 +13805,64 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13120
13805
|
if (skill === "components" && allComponents && sessionId2) {
|
|
13121
13806
|
const db = openPipelineDb();
|
|
13122
13807
|
let componentResults;
|
|
13808
|
+
const precomputedCachedNames = parsePrecomputedCachedNames(opts.cachedComponents);
|
|
13123
13809
|
try {
|
|
13810
|
+
const existingContentfulEntitiesHashInputs = [];
|
|
13811
|
+
if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
|
|
13812
|
+
const promptHash = await hashPromptForSkill(
|
|
13813
|
+
"components",
|
|
13814
|
+
agent,
|
|
13815
|
+
model,
|
|
13816
|
+
generatePromptPath,
|
|
13817
|
+
existingContentfulEntitiesHashInputs,
|
|
13818
|
+
generatePrompt
|
|
13819
|
+
);
|
|
13820
|
+
if (opts.cacheStatus) {
|
|
13821
|
+
const cacheEnabled = opts.cache !== false && process.env.EDS_NO_CACHE !== "1";
|
|
13822
|
+
const cachedComponents = cacheEnabled ? allComponents.flatMap((component) => {
|
|
13823
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13824
|
+
return resolution ? [{ component, resolution }] : [];
|
|
13825
|
+
}) : [];
|
|
13826
|
+
if (cacheEnabled && opts.restoreCache) {
|
|
13827
|
+
const restorations = [];
|
|
13828
|
+
const rekeyed = [];
|
|
13829
|
+
const componentStatus = db.prepare(
|
|
13830
|
+
"SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?"
|
|
13831
|
+
);
|
|
13832
|
+
for (const { component, resolution } of cachedComponents) {
|
|
13833
|
+
const current = componentStatus.get(sessionId2, component.component_id);
|
|
13834
|
+
if (current?.status === "generated") continue;
|
|
13835
|
+
renameEmptySlots(db, sessionId2, component.component_id, component.name, component.slots.length);
|
|
13836
|
+
restorations.push({
|
|
13837
|
+
sourceSessionId: resolution.entry.sourceSessionId,
|
|
13838
|
+
targetSessionId: sessionId2,
|
|
13839
|
+
componentId: component.component_id
|
|
13840
|
+
});
|
|
13841
|
+
rekeyed.push({ component, cached: resolution.entry });
|
|
13842
|
+
}
|
|
13843
|
+
copyComponentsFromCache(db, restorations, { allowedComponentNames: allowedComponentNames2 });
|
|
13844
|
+
storeCaches(
|
|
13845
|
+
db,
|
|
13846
|
+
rekeyed.map(({ component, cached }) => ({
|
|
13847
|
+
inputHash: hashComponentShape(normalizeComponentForCache(component)),
|
|
13848
|
+
entityType: "component",
|
|
13849
|
+
entityId: component.component_id,
|
|
13850
|
+
sourceSessionId: cached.sourceSessionId,
|
|
13851
|
+
humanEdited: cached.humanEdited,
|
|
13852
|
+
promptHash
|
|
13853
|
+
}))
|
|
13854
|
+
);
|
|
13855
|
+
}
|
|
13856
|
+
const fullyCached = cacheEnabled && cachedComponents.length === allComponents.length;
|
|
13857
|
+
process.stdout.write(`cache-status=${fullyCached ? "hit" : "miss"}
|
|
13858
|
+
`);
|
|
13859
|
+
process.stdout.write(
|
|
13860
|
+
`cache-components=${JSON.stringify(cachedComponents.map(({ component }) => component.name))}
|
|
13861
|
+
`
|
|
13862
|
+
);
|
|
13863
|
+
await exitWithAnalytics(0);
|
|
13864
|
+
return;
|
|
13865
|
+
}
|
|
13124
13866
|
componentResults = await runAllComponents(
|
|
13125
13867
|
{
|
|
13126
13868
|
agent,
|
|
@@ -13130,10 +13872,13 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13130
13872
|
tokensInline,
|
|
13131
13873
|
tokenMapInline,
|
|
13132
13874
|
verbose,
|
|
13875
|
+
noCache: opts.cache === false || process.env.EDS_NO_CACHE === "1",
|
|
13133
13876
|
skillPathOverride: generatePromptPath,
|
|
13134
13877
|
skillContentOverride: generatePrompt,
|
|
13878
|
+
promptHash,
|
|
13135
13879
|
existingContentfulEntities,
|
|
13136
13880
|
existingTokensInline,
|
|
13881
|
+
precomputedCachedNames,
|
|
13137
13882
|
allowedComponentNames: allowedComponentNames2
|
|
13138
13883
|
},
|
|
13139
13884
|
allComponents
|
|
@@ -13142,7 +13887,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13142
13887
|
db.close();
|
|
13143
13888
|
}
|
|
13144
13889
|
const failed = componentResults.filter((r) => r.failed);
|
|
13145
|
-
const
|
|
13890
|
+
const cachedResults = componentResults.filter((r) => r.cached);
|
|
13891
|
+
const generated = componentResults.filter((r) => !r.failed && !r.cached);
|
|
13146
13892
|
const allWarnings = componentResults.flatMap((r) => r.warnings.map((w) => ` ${r.componentName}: ${w}`));
|
|
13147
13893
|
if (allWarnings.length > 0) {
|
|
13148
13894
|
process.stderr.write(c.yellow("Warnings:") + "\n" + allWarnings.join("\n") + "\n");
|
|
@@ -13158,17 +13904,21 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13158
13904
|
const totalExcluded = generated.reduce((s, r) => s + r.excluded, 0);
|
|
13159
13905
|
const totalRenamedSlots = componentResults.reduce((s, r) => s + r.renamedSlotsCount, 0);
|
|
13160
13906
|
const allOk = failed.length === 0;
|
|
13907
|
+
const cachedNote = cachedResults.length > 0 ? c.dim(` (${cachedResults.length} cached)`) : "";
|
|
13161
13908
|
process.stderr.write(
|
|
13162
|
-
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length}/${componentResults.length} components` + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13909
|
+
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length + cachedResults.length}/${componentResults.length} components` + cachedNote + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13163
13910
|
);
|
|
13164
13911
|
process.stdout.write(`renamed-slots: ${totalRenamedSlots}
|
|
13165
13912
|
`);
|
|
13166
|
-
if (generated.length === 0) {
|
|
13913
|
+
if (generated.length === 0 && cachedResults.length === 0) {
|
|
13167
13914
|
die(
|
|
13168
13915
|
`Error: all ${componentResults.length} component(s) failed to generate \u2014 see the per-component errors above.`
|
|
13169
13916
|
);
|
|
13170
13917
|
}
|
|
13171
13918
|
} else if (skill === "tokens") {
|
|
13919
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
13920
|
+
const tokenInputContent = rawTokensInline ?? "";
|
|
13921
|
+
const tokenInputHash = hashTokenContent(tokenInputContent);
|
|
13172
13922
|
const db = openPipelineDb();
|
|
13173
13923
|
try {
|
|
13174
13924
|
let resolvedSessionId = opts.session;
|
|
@@ -13195,11 +13945,26 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13195
13945
|
}
|
|
13196
13946
|
sessionId2 = resolvedSessionId;
|
|
13197
13947
|
await bindAnalyticsSessionId(resolvedSessionId);
|
|
13948
|
+
const tokenPromptHash = await hashPromptForSkill("tokens", agent, model);
|
|
13949
|
+
if (!noCache) {
|
|
13950
|
+
const tokenCached = lookupCache(db, tokenInputHash, "token_set", "__tokens__", tokenPromptHash);
|
|
13951
|
+
if (tokenCached) {
|
|
13952
|
+
copyTokensFromCache(db, tokenCached.sourceSessionId, resolvedSessionId);
|
|
13953
|
+
sessionId2 = resolvedSessionId;
|
|
13954
|
+
process.stderr.write(
|
|
13955
|
+
`Done: tokens reused from cache ${c.dim(`(source: ${tokenCached.sourceSessionId.slice(0, 12)})`)}
|
|
13956
|
+
`
|
|
13957
|
+
);
|
|
13958
|
+
db.close();
|
|
13959
|
+
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13960
|
+
return;
|
|
13961
|
+
}
|
|
13962
|
+
}
|
|
13198
13963
|
const prompt = await buildPrompt({
|
|
13199
13964
|
skill,
|
|
13200
13965
|
mode: "autonomous",
|
|
13201
13966
|
rawTokensInline,
|
|
13202
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13967
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13203
13968
|
tokensInline,
|
|
13204
13969
|
tokenMapInline,
|
|
13205
13970
|
outDir: process.cwd()
|
|
@@ -13236,6 +14001,9 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13236
14001
|
`);
|
|
13237
14002
|
}
|
|
13238
14003
|
applyTokenToolCalls(db, resolvedSessionId, tokenCalls, []);
|
|
14004
|
+
if (!noCache) {
|
|
14005
|
+
storeCache(db, tokenInputHash, "token_set", "__tokens__", resolvedSessionId, false, tokenPromptHash);
|
|
14006
|
+
}
|
|
13239
14007
|
sessionId2 = resolvedSessionId;
|
|
13240
14008
|
const groupCount = tokenCalls.filter((tc) => tc.tool === "set_group").length;
|
|
13241
14009
|
process.stderr.write(`Done: ${tokenCount} tokens, ${groupCount} groups stored
|
|
@@ -13247,7 +14015,10 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13247
14015
|
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13248
14016
|
}
|
|
13249
14017
|
function addAgentFlags(cmd) {
|
|
13250
|
-
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent")
|
|
14018
|
+
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent").option(
|
|
14019
|
+
"--no-cache",
|
|
14020
|
+
"Bypass ALL fine-grained caches (extract, select, generate) and force AI re-run. Cache keys now factor in prompt content \u2014 changing the prompt file via --generate-prompt-path or --select-prompt-path will already bust the corresponding stage. Use --no-cache to force a full re-run."
|
|
14021
|
+
);
|
|
13251
14022
|
}
|
|
13252
14023
|
function registerInternalGenerateCommand(program) {
|
|
13253
14024
|
const generate = program.command("__generate", { hidden: true }).description("Internal import pipeline generation command");
|
|
@@ -13263,6 +14034,12 @@ function registerInternalGenerateCommand(program) {
|
|
|
13263
14034
|
"--existing-entities-path <path>",
|
|
13264
14035
|
"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."
|
|
13265
14036
|
);
|
|
14037
|
+
componentsCmd.option("--cache-status", "Check whether all selected component definitions are cached");
|
|
14038
|
+
componentsCmd.option("--restore-cache", "Restore cached component definitions into the current session");
|
|
14039
|
+
componentsCmd.option(
|
|
14040
|
+
"--cached-components <json>",
|
|
14041
|
+
"Component names already restored by a prior cache-status lookup; skip per-component cache lookup"
|
|
14042
|
+
);
|
|
13266
14043
|
addAgentFlags(componentsCmd).action(async (opts) => {
|
|
13267
14044
|
await runGenerateSkill("components", opts, opts.verbose ?? false);
|
|
13268
14045
|
});
|
|
@@ -13290,6 +14067,7 @@ var init_command = __esm({
|
|
|
13290
14067
|
init_agent_output();
|
|
13291
14068
|
init_GenerateView();
|
|
13292
14069
|
init_db();
|
|
14070
|
+
init_cache_keys();
|
|
13293
14071
|
init_read_existing_contentful_entities_from_session();
|
|
13294
14072
|
init_summarize_existing_contentful_entities();
|
|
13295
14073
|
init_resolve_session_id();
|
|
@@ -14005,7 +14783,7 @@ var init_user_agent = __esm({
|
|
|
14005
14783
|
// packages/experience-design-system-cli-legacy/src/apply/api-client.ts
|
|
14006
14784
|
import { parseCDFComponents } from "@contentful/experience-design-system-types";
|
|
14007
14785
|
function defaultSleep(delayMs) {
|
|
14008
|
-
return new Promise((
|
|
14786
|
+
return new Promise((resolve21) => setTimeout(resolve21, delayMs));
|
|
14009
14787
|
}
|
|
14010
14788
|
function isTransientStatus(status) {
|
|
14011
14789
|
return status >= 500 && status <= 599;
|
|
@@ -14395,7 +15173,7 @@ ${trimmed}`;
|
|
|
14395
15173
|
const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
|
|
14396
15174
|
const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
|
|
14397
15175
|
const jitter = Math.random() * baseDelay * 0.15;
|
|
14398
|
-
await new Promise((
|
|
15176
|
+
await new Promise((resolve21) => setTimeout(resolve21, baseDelay + jitter));
|
|
14399
15177
|
}
|
|
14400
15178
|
}
|
|
14401
15179
|
throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
|
|
@@ -15205,7 +15983,7 @@ var init_terminal_capabilities = __esm({
|
|
|
15205
15983
|
|
|
15206
15984
|
// packages/experience-design-system-cli-legacy/src/apply/command.ts
|
|
15207
15985
|
import { createElement as createElement2 } from "react";
|
|
15208
|
-
import { readFile as
|
|
15986
|
+
import { readFile as readFile13, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
15209
15987
|
import { join as join16 } from "node:path";
|
|
15210
15988
|
import {
|
|
15211
15989
|
validateCDF,
|
|
@@ -15226,7 +16004,7 @@ function dieWithApiError(error) {
|
|
|
15226
16004
|
async function readJsonFile(flag, p) {
|
|
15227
16005
|
let text;
|
|
15228
16006
|
try {
|
|
15229
|
-
text = await
|
|
16007
|
+
text = await readFile13(p, "utf8");
|
|
15230
16008
|
} catch {
|
|
15231
16009
|
return await die2(`Error: file not found: ${p} (from ${flag})`);
|
|
15232
16010
|
}
|
|
@@ -15280,7 +16058,7 @@ async function readTokensFromPath(flag, p) {
|
|
|
15280
16058
|
for (const file of files.sort()) {
|
|
15281
16059
|
let text;
|
|
15282
16060
|
try {
|
|
15283
|
-
text = await
|
|
16061
|
+
text = await readFile13(file, "utf8");
|
|
15284
16062
|
} catch {
|
|
15285
16063
|
continue;
|
|
15286
16064
|
}
|
|
@@ -15649,11 +16427,11 @@ var init_command2 = __esm({
|
|
|
15649
16427
|
});
|
|
15650
16428
|
|
|
15651
16429
|
// packages/experience-design-system-cli-legacy/src/print/validate/validators/read-json-file.ts
|
|
15652
|
-
import { readFile as
|
|
16430
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
15653
16431
|
async function readJsonFile2(filePath) {
|
|
15654
16432
|
let content;
|
|
15655
16433
|
try {
|
|
15656
|
-
content = await
|
|
16434
|
+
content = await readFile14(filePath, "utf-8");
|
|
15657
16435
|
} catch (err) {
|
|
15658
16436
|
return {
|
|
15659
16437
|
ok: false,
|
|
@@ -16064,7 +16842,7 @@ var init_ValidateView = __esm({
|
|
|
16064
16842
|
// packages/experience-design-system-cli-legacy/src/print/command.ts
|
|
16065
16843
|
import { createElement as createElement3 } from "react";
|
|
16066
16844
|
import { access as access3, mkdir as mkdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
16067
|
-
import { basename as basename5, resolve as
|
|
16845
|
+
import { basename as basename5, resolve as resolve13 } from "node:path";
|
|
16068
16846
|
import { CDF_SCHEMA_URL } from "@contentful/experience-design-system-types";
|
|
16069
16847
|
async function die3(message) {
|
|
16070
16848
|
process.stderr.write(`${message}
|
|
@@ -16131,7 +16909,7 @@ function registerPrintCommand(program) {
|
|
|
16131
16909
|
"--allow-empty",
|
|
16132
16910
|
"Write an empty-but-present CDF file when no components are accepted (a subsequent push then removes ALL components from the target space). Without this, an empty accepted set is an error."
|
|
16133
16911
|
).action(async (opts) => {
|
|
16134
|
-
const outPath =
|
|
16912
|
+
const outPath = resolve13(opts.out);
|
|
16135
16913
|
await assertOutIsNotDirectory(outPath);
|
|
16136
16914
|
const sessionId2 = await resolveSession(opts.session, "generate components");
|
|
16137
16915
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16179,7 +16957,7 @@ function registerPrintCommand(program) {
|
|
|
16179
16957
|
`
|
|
16180
16958
|
);
|
|
16181
16959
|
}
|
|
16182
|
-
await mkdir3(
|
|
16960
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16183
16961
|
await writeFile3(outPath, `${JSON.stringify(cdfObj, null, 2)}
|
|
16184
16962
|
`);
|
|
16185
16963
|
process.stdout.write(
|
|
@@ -16188,7 +16966,7 @@ function registerPrintCommand(program) {
|
|
|
16188
16966
|
);
|
|
16189
16967
|
});
|
|
16190
16968
|
print.command("tokens").description("Write generated tokens to a DTCG JSON file").option("--session <id>", "Session ID to print from (default: most recent generate tokens session)").option("--out <path>", "Output file path", "tokens.json").action(async (opts) => {
|
|
16191
|
-
const outPath =
|
|
16969
|
+
const outPath = resolve13(opts.out);
|
|
16192
16970
|
await assertOutIsNotDirectory(outPath);
|
|
16193
16971
|
const sessionId2 = await resolveSession(opts.session, "generate tokens");
|
|
16194
16972
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16203,7 +16981,7 @@ function registerPrintCommand(program) {
|
|
|
16203
16981
|
await die3(`Error: no generated tokens in session '${sessionId2}'. Run generate tokens first.`);
|
|
16204
16982
|
}
|
|
16205
16983
|
const tree = rebuildDTCGTree(result.groups, result.tokens);
|
|
16206
|
-
await mkdir3(
|
|
16984
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16207
16985
|
await writeFile3(outPath, `${JSON.stringify(tree, null, 2)}
|
|
16208
16986
|
`);
|
|
16209
16987
|
process.stdout.write(
|
|
@@ -16352,7 +17130,7 @@ function MapTokensView({ result, onExit }) {
|
|
|
16352
17130
|
const timer = setTimeout(onExit, 100);
|
|
16353
17131
|
return () => clearTimeout(timer);
|
|
16354
17132
|
}, [onExit]);
|
|
16355
|
-
const summary = `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
17133
|
+
const summary = result.cached ? "reused from cache" : `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
16356
17134
|
return /* @__PURE__ */ jsx8(
|
|
16357
17135
|
CommandCompletionView,
|
|
16358
17136
|
{
|
|
@@ -16486,8 +17264,8 @@ var init_resolve_defaults = __esm({
|
|
|
16486
17264
|
|
|
16487
17265
|
// packages/experience-design-system-cli-legacy/src/map-tokens/command.ts
|
|
16488
17266
|
import { createElement as createElement4 } from "react";
|
|
16489
|
-
import { readFile as
|
|
16490
|
-
import { resolve as
|
|
17267
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
17268
|
+
import { resolve as resolve14 } from "node:path";
|
|
16491
17269
|
async function renderResult(result) {
|
|
16492
17270
|
if (process.stdout.isTTY) {
|
|
16493
17271
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -16495,13 +17273,12 @@ async function renderResult(result) {
|
|
|
16495
17273
|
);
|
|
16496
17274
|
await waitUntilExit();
|
|
16497
17275
|
} else {
|
|
16498
|
-
|
|
16499
|
-
|
|
17276
|
+
const summary = result.cached ? "cached" : `${result.applied} mapping(s) applied`;
|
|
17277
|
+
process.stdout.write(`map tokens complete
|
|
16500
17278
|
agent: ${result.agent}
|
|
16501
17279
|
session=${result.sessionId}
|
|
16502
|
-
${
|
|
16503
|
-
`
|
|
16504
|
-
);
|
|
17280
|
+
${summary}
|
|
17281
|
+
`);
|
|
16505
17282
|
await exitWithAnalytics(0);
|
|
16506
17283
|
}
|
|
16507
17284
|
}
|
|
@@ -16523,7 +17300,7 @@ async function runMapTokens(opts) {
|
|
|
16523
17300
|
let mapPromptPath;
|
|
16524
17301
|
if (mapPromptOverride?.kind === "text") mapPromptText = mapPromptOverride.value;
|
|
16525
17302
|
if (mapPromptOverride?.kind === "path") {
|
|
16526
|
-
mapPromptPath =
|
|
17303
|
+
mapPromptPath = resolve14(mapPromptOverride.value);
|
|
16527
17304
|
try {
|
|
16528
17305
|
await resolvePromptOverride(mapPromptOverride);
|
|
16529
17306
|
} catch (error) {
|
|
@@ -16543,7 +17320,7 @@ async function runMapTokens(opts) {
|
|
|
16543
17320
|
const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
|
|
16544
17321
|
const tokenMapDiagnostics = [];
|
|
16545
17322
|
if (opts.tokenMap) {
|
|
16546
|
-
const fileMappings = JSON.parse(await
|
|
17323
|
+
const fileMappings = JSON.parse(await readFile15(opts.tokenMap, "utf8"));
|
|
16547
17324
|
const validMappings = {};
|
|
16548
17325
|
for (const [rawName, path] of Object.entries(fileMappings)) {
|
|
16549
17326
|
if (knownTokenPaths.has(path)) {
|
|
@@ -16621,7 +17398,7 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16621
17398
|
let existingTokensInline;
|
|
16622
17399
|
if (opts.existingEntitiesPath) {
|
|
16623
17400
|
const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
16624
|
-
|
|
17401
|
+
resolve14(opts.existingEntitiesPath)
|
|
16625
17402
|
);
|
|
16626
17403
|
if (existingContentfulEntities) {
|
|
16627
17404
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
@@ -16656,10 +17433,30 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16656
17433
|
skipAgent: "true"
|
|
16657
17434
|
});
|
|
16658
17435
|
updateStep(db, stepId2, "complete", { applied: "0", skipAgent: "true" });
|
|
16659
|
-
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0 });
|
|
17436
|
+
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0, cached: false });
|
|
16660
17437
|
return;
|
|
16661
17438
|
}
|
|
16662
17439
|
const agent = configuredAgent;
|
|
17440
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
17441
|
+
const promptHash = await hashPromptForSkill(
|
|
17442
|
+
"map-tokens",
|
|
17443
|
+
agent,
|
|
17444
|
+
model,
|
|
17445
|
+
void 0,
|
|
17446
|
+
existingTokensInline ? [hashContent(existingTokensInline)] : [],
|
|
17447
|
+
mapPromptText
|
|
17448
|
+
);
|
|
17449
|
+
const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
|
|
17450
|
+
if (!noCache) {
|
|
17451
|
+
const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
|
|
17452
|
+
if (cached) {
|
|
17453
|
+
const appliedFromCache = copyMapTokensFromCache(db, cached.sourceSessionId, sessionId2);
|
|
17454
|
+
const stepId2 = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
|
|
17455
|
+
updateStep(db, stepId2, "complete", { cached: "true", applied: String(appliedFromCache) });
|
|
17456
|
+
await renderResult({ agent, sessionId: sessionId2, applied: appliedFromCache, cached: true });
|
|
17457
|
+
return;
|
|
17458
|
+
}
|
|
17459
|
+
}
|
|
16663
17460
|
const binary = resolveAgentBinary(agent);
|
|
16664
17461
|
if (!await assertBinaryInPath(binary)) {
|
|
16665
17462
|
die(
|
|
@@ -16679,20 +17476,23 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
16679
17476
|
}
|
|
16680
17477
|
const { calls, warnings: parseWarnings } = parseMapTokenPropToolCallLines(result.stdout);
|
|
16681
17478
|
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, calls, parseWarnings);
|
|
17479
|
+
if (!noCache) {
|
|
17480
|
+
storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId2, false, promptHash);
|
|
17481
|
+
}
|
|
16682
17482
|
updateStep(db, stepId, "complete", { applied: String(applied), warnings: String(warnings.length) });
|
|
16683
17483
|
if (warnings.length > 0) {
|
|
16684
17484
|
process.stderr.write(`Warnings:
|
|
16685
17485
|
${warnings.map((w) => ` ${w}`).join("\n")}
|
|
16686
17486
|
`);
|
|
16687
17487
|
}
|
|
16688
|
-
await renderResult({ agent, sessionId: sessionId2, applied });
|
|
17488
|
+
await renderResult({ agent, sessionId: sessionId2, applied, cached: false });
|
|
16689
17489
|
} finally {
|
|
16690
17490
|
db.close();
|
|
16691
17491
|
}
|
|
16692
17492
|
}
|
|
16693
17493
|
function registerMapTokensCommand(program) {
|
|
16694
17494
|
const map = program.command("map", { hidden: true }).description("Suggest token restrictions for generated design-token props");
|
|
16695
|
-
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option(
|
|
17495
|
+
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option("--no-cache", "Bypass the map-tokens cache and force a re-run").option(
|
|
16696
17496
|
"--prompt <stage=value>",
|
|
16697
17497
|
"Override a stage prompt (repeatable). Used here for the map-tokens stage.",
|
|
16698
17498
|
(v, acc) => [...acc, v],
|
|
@@ -16712,6 +17512,7 @@ var init_command4 = __esm({
|
|
|
16712
17512
|
init_render_with_goodbye();
|
|
16713
17513
|
init_src();
|
|
16714
17514
|
init_db();
|
|
17515
|
+
init_cache_keys();
|
|
16715
17516
|
init_read_existing_contentful_entities_from_session();
|
|
16716
17517
|
init_summarize_existing_contentful_entities();
|
|
16717
17518
|
init_command3();
|
|
@@ -16728,7 +17529,7 @@ var init_command4 = __esm({
|
|
|
16728
17529
|
});
|
|
16729
17530
|
|
|
16730
17531
|
// packages/experience-design-system-cli-legacy/src/import/path-utils.ts
|
|
16731
|
-
import { resolve as
|
|
17532
|
+
import { resolve as resolve15 } from "node:path";
|
|
16732
17533
|
import { homedir as homedir5 } from "node:os";
|
|
16733
17534
|
function expandTilde(input) {
|
|
16734
17535
|
if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
|
|
@@ -16742,7 +17543,7 @@ function normalizePath(input) {
|
|
|
16742
17543
|
p = p.slice(1, -1);
|
|
16743
17544
|
}
|
|
16744
17545
|
p = expandTilde(p);
|
|
16745
|
-
return
|
|
17546
|
+
return resolve15(p);
|
|
16746
17547
|
}
|
|
16747
17548
|
var init_path_utils = __esm({
|
|
16748
17549
|
"packages/experience-design-system-cli-legacy/src/import/path-utils.ts"() {
|
|
@@ -16967,7 +17768,7 @@ var init_save_path_resolver = __esm({
|
|
|
16967
17768
|
});
|
|
16968
17769
|
|
|
16969
17770
|
// packages/experience-design-system-cli-legacy/src/runs/store.ts
|
|
16970
|
-
import { readFile as
|
|
17771
|
+
import { readFile as readFile16, writeFile as writeFile4, mkdir as mkdir4, rename } from "node:fs/promises";
|
|
16971
17772
|
import { join as join20 } from "node:path";
|
|
16972
17773
|
import { homedir as homedir6 } from "node:os";
|
|
16973
17774
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -17007,7 +17808,7 @@ function migrateRecord(rec) {
|
|
|
17007
17808
|
}
|
|
17008
17809
|
async function readFileMaybe() {
|
|
17009
17810
|
try {
|
|
17010
|
-
const raw = await
|
|
17811
|
+
const raw = await readFile16(RUNS_PATH, "utf8");
|
|
17011
17812
|
const parsed = JSON.parse(raw);
|
|
17012
17813
|
if (!READABLE_VERSIONS.has(parsed.version)) {
|
|
17013
17814
|
throw new Error(
|
|
@@ -17071,15 +17872,15 @@ var init_store = __esm({
|
|
|
17071
17872
|
});
|
|
17072
17873
|
|
|
17073
17874
|
// packages/experience-design-system-cli-legacy/src/runs/fingerprint.ts
|
|
17074
|
-
import { createHash as
|
|
17075
|
-
import { readFile as
|
|
17076
|
-
import { resolve as
|
|
17875
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
17876
|
+
import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
|
|
17877
|
+
import { resolve as resolve16 } from "node:path";
|
|
17077
17878
|
function rowField(row, key) {
|
|
17078
17879
|
const v = row[key];
|
|
17079
17880
|
return typeof v === "string" ? v : null;
|
|
17080
17881
|
}
|
|
17081
17882
|
function sha256Hex(buf) {
|
|
17082
|
-
return
|
|
17883
|
+
return createHash6("sha256").update(buf).digest("hex");
|
|
17083
17884
|
}
|
|
17084
17885
|
async function buildSourceFingerprint(opts) {
|
|
17085
17886
|
const rows = opts.db.prepare("SELECT name, source_path FROM raw_components WHERE session_id = ?").all(opts.extractSessionId);
|
|
@@ -17089,7 +17890,7 @@ async function buildSourceFingerprint(opts) {
|
|
|
17089
17890
|
const sourcePath = rowField(row, "source_path");
|
|
17090
17891
|
const name = rowField(row, "name");
|
|
17091
17892
|
if (!sourcePath) continue;
|
|
17092
|
-
const abs =
|
|
17893
|
+
const abs = resolve16(sourcePath);
|
|
17093
17894
|
if (seen.has(abs)) continue;
|
|
17094
17895
|
seen.add(abs);
|
|
17095
17896
|
try {
|
|
@@ -17104,10 +17905,10 @@ async function buildSourceFingerprint(opts) {
|
|
|
17104
17905
|
let rawTokensMtime = null;
|
|
17105
17906
|
let rawTokensContentHash = null;
|
|
17106
17907
|
if (opts.rawTokensPath) {
|
|
17107
|
-
const abs =
|
|
17908
|
+
const abs = resolve16(opts.rawTokensPath);
|
|
17108
17909
|
rawTokensPath = abs;
|
|
17109
17910
|
try {
|
|
17110
|
-
const [st, buf] = await Promise.all([stat4(abs),
|
|
17911
|
+
const [st, buf] = await Promise.all([stat4(abs), readFile17(abs)]);
|
|
17111
17912
|
rawTokensMtime = st.mtime.toISOString();
|
|
17112
17913
|
rawTokensContentHash = sha256Hex(buf);
|
|
17113
17914
|
} catch {
|
|
@@ -18862,11 +19663,11 @@ var init_slot_graph = __esm({
|
|
|
18862
19663
|
});
|
|
18863
19664
|
|
|
18864
19665
|
// packages/experience-design-system-cli-legacy/src/analyze/select/parser.ts
|
|
18865
|
-
import { createHash as
|
|
19666
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
18866
19667
|
import { access as access5 } from "node:fs/promises";
|
|
18867
|
-
import { isAbsolute, relative, resolve as
|
|
19668
|
+
import { isAbsolute, relative, resolve as resolve17 } from "node:path";
|
|
18868
19669
|
function createComponentId(name, resolvedSourcePath) {
|
|
18869
|
-
const sourceHash =
|
|
19670
|
+
const sourceHash = createHash7("sha256").update(`${name}:${resolvedSourcePath}`).digest("hex").slice(0, 12);
|
|
18870
19671
|
return `${name}-${sourceHash}`;
|
|
18871
19672
|
}
|
|
18872
19673
|
async function resolveComponentSourcePath(source, reviewRoot) {
|
|
@@ -18878,7 +19679,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18878
19679
|
throw new Error(`Unable to access component source at ${source}`);
|
|
18879
19680
|
}
|
|
18880
19681
|
}
|
|
18881
|
-
const candidate =
|
|
19682
|
+
const candidate = resolve17(reviewRoot, source);
|
|
18882
19683
|
const relativeToRoot = relative(reviewRoot, candidate);
|
|
18883
19684
|
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || isAbsolute(relativeToRoot)) {
|
|
18884
19685
|
throw new Error(
|
|
@@ -18893,7 +19694,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18893
19694
|
}
|
|
18894
19695
|
}
|
|
18895
19696
|
async function loadReviewInput(components, options = {}) {
|
|
18896
|
-
const reviewRoot =
|
|
19697
|
+
const reviewRoot = resolve17(options.reviewRoot ?? process.cwd());
|
|
18897
19698
|
const records = await Promise.all(
|
|
18898
19699
|
components.map(async (component) => {
|
|
18899
19700
|
let resolvedSourcePath;
|
|
@@ -18924,7 +19725,7 @@ var init_parser = __esm({
|
|
|
18924
19725
|
});
|
|
18925
19726
|
|
|
18926
19727
|
// packages/experience-design-system-cli-legacy/src/analyze/select/command.ts
|
|
18927
|
-
import { access as access6, readFile as
|
|
19728
|
+
import { access as access6, readFile as readFile18 } from "node:fs/promises";
|
|
18928
19729
|
async function loadAndValidateForReview(sessionId2, projectRoot) {
|
|
18929
19730
|
const db = openPipelineDb();
|
|
18930
19731
|
let rawComponents;
|
|
@@ -18942,7 +19743,7 @@ async function patchReviewStateWithValidationErrors(sessionId2, errors, opts = {
|
|
|
18942
19743
|
let snapshot;
|
|
18943
19744
|
try {
|
|
18944
19745
|
await access6(paths.statePath);
|
|
18945
|
-
snapshot = JSON.parse(await
|
|
19746
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18946
19747
|
} catch {
|
|
18947
19748
|
snapshot = await loadAndValidateForReview(sessionId2, void 0);
|
|
18948
19749
|
snapshot = await ensureRefineSession(sessionId2, artifactsRoot, snapshot);
|
|
@@ -18993,7 +19794,7 @@ async function rejectComponentsByName(sessionId2, names, opts = {}) {
|
|
|
18993
19794
|
const nameSet = new Set(names);
|
|
18994
19795
|
let snapshot;
|
|
18995
19796
|
try {
|
|
18996
|
-
snapshot = JSON.parse(await
|
|
19797
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18997
19798
|
} catch {
|
|
18998
19799
|
return;
|
|
18999
19800
|
}
|
|
@@ -19092,9 +19893,9 @@ function spawnGenerateChild(opts) {
|
|
|
19092
19893
|
stderr += chunk;
|
|
19093
19894
|
opts.onStderr?.(chunk);
|
|
19094
19895
|
});
|
|
19095
|
-
const donePromise = new Promise((
|
|
19896
|
+
const donePromise = new Promise((resolve21) => {
|
|
19096
19897
|
child.on("close", (code, signal) => {
|
|
19097
|
-
|
|
19898
|
+
resolve21({
|
|
19098
19899
|
exitCode: code ?? 0,
|
|
19099
19900
|
signal: signal ?? null,
|
|
19100
19901
|
stdout,
|
|
@@ -19102,7 +19903,7 @@ function spawnGenerateChild(opts) {
|
|
|
19102
19903
|
});
|
|
19103
19904
|
});
|
|
19104
19905
|
child.on("error", (err) => {
|
|
19105
|
-
|
|
19906
|
+
resolve21({
|
|
19106
19907
|
exitCode: 1,
|
|
19107
19908
|
signal: null,
|
|
19108
19909
|
stdout,
|
|
@@ -27240,6 +28041,9 @@ function shouldGenerateAfterCredentialsValidated(opts) {
|
|
|
27240
28041
|
function shouldSkipFinalReviewAfterCredentials(state) {
|
|
27241
28042
|
return state.finalReviewPassed && state.generateSessionId != null;
|
|
27242
28043
|
}
|
|
28044
|
+
function resolveNoCacheForGenerate(opts) {
|
|
28045
|
+
return opts.cliNoCache;
|
|
28046
|
+
}
|
|
27243
28047
|
function shouldBypassPreview(state) {
|
|
27244
28048
|
return state.credentialsSkipped === true;
|
|
27245
28049
|
}
|
|
@@ -27266,39 +28070,66 @@ var init_wizard_state_transitions = __esm({
|
|
|
27266
28070
|
async function runSelectionAgent(options) {
|
|
27267
28071
|
const db = openPipelineDb();
|
|
27268
28072
|
let components;
|
|
28073
|
+
const cachedDecisions = /* @__PURE__ */ new Map();
|
|
28074
|
+
const cliVersion2 = await getCliCacheVersion();
|
|
28075
|
+
const promptHash = await hashPromptForSkill(
|
|
28076
|
+
"select",
|
|
28077
|
+
options.agent,
|
|
28078
|
+
options.model,
|
|
28079
|
+
options.promptPath,
|
|
28080
|
+
[SELECT_PAYLOAD_FORMAT],
|
|
28081
|
+
options.promptText
|
|
28082
|
+
);
|
|
27269
28083
|
try {
|
|
27270
28084
|
components = loadRawComponents(db, options.sessionId);
|
|
28085
|
+
if (!options.noCache) {
|
|
28086
|
+
for (const component of components) {
|
|
28087
|
+
const componentHash = hashComponentShape(component);
|
|
28088
|
+
const cached = lookupSelectCache(db, componentHash, promptHash, cliVersion2);
|
|
28089
|
+
if (cached) {
|
|
28090
|
+
cachedDecisions.set(component.name, {
|
|
28091
|
+
decision: cached.decision,
|
|
28092
|
+
reason: cached.reason
|
|
28093
|
+
});
|
|
28094
|
+
}
|
|
28095
|
+
}
|
|
28096
|
+
}
|
|
27271
28097
|
} finally {
|
|
27272
28098
|
db.close();
|
|
27273
28099
|
}
|
|
27274
28100
|
if (components.length === 0) return;
|
|
27275
|
-
const
|
|
27276
|
-
|
|
27277
|
-
|
|
27278
|
-
|
|
27279
|
-
|
|
27280
|
-
|
|
27281
|
-
|
|
27282
|
-
|
|
27283
|
-
|
|
27284
|
-
|
|
27285
|
-
|
|
27286
|
-
|
|
27287
|
-
|
|
27288
|
-
|
|
27289
|
-
|
|
27290
|
-
|
|
27291
|
-
|
|
27292
|
-
|
|
27293
|
-
|
|
27294
|
-
|
|
27295
|
-
|
|
27296
|
-
|
|
27297
|
-
|
|
27298
|
-
|
|
27299
|
-
|
|
28101
|
+
const componentsToRun = components.filter((component) => !cachedDecisions.has(component.name));
|
|
28102
|
+
let calls = [];
|
|
28103
|
+
if (componentsToRun.length > 0) {
|
|
28104
|
+
const invoker2 = createLocalCliAgentInvoker({
|
|
28105
|
+
onDebugEvent: (name, payload) => getDebugLogger().event("agent", name, payload)
|
|
28106
|
+
});
|
|
28107
|
+
const prompt = await buildPrompt({
|
|
28108
|
+
skill: "select",
|
|
28109
|
+
mode: "autonomous",
|
|
28110
|
+
rawComponentsInline: JSON.stringify(
|
|
28111
|
+
componentsToRun.map((component) => ({ ...component, props: component.props.map(stripPropProvenance) })),
|
|
28112
|
+
null,
|
|
28113
|
+
2
|
|
28114
|
+
),
|
|
28115
|
+
propBucketsInline: logPropBuckets("select", bucketComponentsProps(componentsToRun)),
|
|
28116
|
+
outDir: process.cwd(),
|
|
28117
|
+
...options.promptText !== void 0 ? { skillContentOverride: options.promptText } : {},
|
|
28118
|
+
...options.promptText === void 0 && options.promptPath ? { skillPathOverride: options.promptPath } : {}
|
|
28119
|
+
});
|
|
28120
|
+
const { result } = await invokeAgentWithOutput(
|
|
28121
|
+
invoker2,
|
|
28122
|
+
{ agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
|
|
28123
|
+
false
|
|
28124
|
+
);
|
|
28125
|
+
if (result.timedOut) throw new Error("selection agent timed out");
|
|
28126
|
+
if (result.exitCode !== 0) throw new Error(`selection agent exited with code ${result.exitCode}`);
|
|
28127
|
+
const parsed = parseSelectToolCallLines(result.stdout);
|
|
28128
|
+
for (const warning of parsed.warnings) process.stderr.write(`Warning: selection agent: ${warning}
|
|
27300
28129
|
`);
|
|
27301
|
-
|
|
28130
|
+
calls = parsed.calls;
|
|
28131
|
+
}
|
|
28132
|
+
const byName = new Map(calls.map((call) => [call.name, call]));
|
|
27302
28133
|
const writeDb = openPipelineDb();
|
|
27303
28134
|
try {
|
|
27304
28135
|
writeDb.exec("BEGIN");
|
|
@@ -27306,15 +28137,27 @@ async function runSelectionAgent(options) {
|
|
|
27306
28137
|
`UPDATE raw_components SET status = ?, reject_reason = ? WHERE session_id = ? AND component_id = ?`
|
|
27307
28138
|
);
|
|
27308
28139
|
for (const component of components) {
|
|
28140
|
+
const cached = cachedDecisions.get(component.name);
|
|
27309
28141
|
const call = byName.get(component.name);
|
|
27310
|
-
if (!call) continue;
|
|
27311
|
-
const rejected = call.tool === "reject_component";
|
|
28142
|
+
if (!cached && !call) continue;
|
|
28143
|
+
const rejected = cached ? cached.decision === "rejected" : call.tool === "reject_component";
|
|
28144
|
+
const reason = cached ? cached.reason : call.reason ?? null;
|
|
27312
28145
|
update.run(
|
|
27313
28146
|
rejected ? "rejected" : "accepted",
|
|
27314
|
-
rejected ?
|
|
28147
|
+
rejected ? reason : null,
|
|
27315
28148
|
options.sessionId,
|
|
27316
28149
|
component.component_id
|
|
27317
28150
|
);
|
|
28151
|
+
if (!cached) {
|
|
28152
|
+
storeSelectCache(
|
|
28153
|
+
writeDb,
|
|
28154
|
+
hashComponentShape(component),
|
|
28155
|
+
promptHash,
|
|
28156
|
+
cliVersion2,
|
|
28157
|
+
rejected ? "rejected" : "accepted",
|
|
28158
|
+
rejected ? reason : null
|
|
28159
|
+
);
|
|
28160
|
+
}
|
|
27318
28161
|
}
|
|
27319
28162
|
writeDb.exec("COMMIT");
|
|
27320
28163
|
} catch (error) {
|
|
@@ -27324,7 +28167,7 @@ async function runSelectionAgent(options) {
|
|
|
27324
28167
|
writeDb.close();
|
|
27325
28168
|
}
|
|
27326
28169
|
}
|
|
27327
|
-
var DEFAULT_TIMEOUT_MS4;
|
|
28170
|
+
var SELECT_PAYLOAD_FORMAT, DEFAULT_TIMEOUT_MS4;
|
|
27328
28171
|
var init_run_selection_agent = __esm({
|
|
27329
28172
|
"packages/experience-design-system-cli-legacy/src/import/tui/run-selection-agent.ts"() {
|
|
27330
28173
|
"use strict";
|
|
@@ -27335,6 +28178,8 @@ var init_run_selection_agent = __esm({
|
|
|
27335
28178
|
init_debug_logger();
|
|
27336
28179
|
init_agent_output();
|
|
27337
28180
|
init_db();
|
|
28181
|
+
init_cache_keys();
|
|
28182
|
+
SELECT_PAYLOAD_FORMAT = "prop-buckets-v1";
|
|
27338
28183
|
DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
|
|
27339
28184
|
}
|
|
27340
28185
|
});
|
|
@@ -27353,7 +28198,7 @@ __export(WizardApp_exports, {
|
|
|
27353
28198
|
});
|
|
27354
28199
|
import { useEffect as useEffect15, useRef as useRef10, useState as useState23 } from "react";
|
|
27355
28200
|
import { Box as Box42, Text as Text46 } from "ink";
|
|
27356
|
-
import { join as join23, resolve as
|
|
28201
|
+
import { join as join23, resolve as resolve18 } from "node:path";
|
|
27357
28202
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27358
28203
|
import { access as access7, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
27359
28204
|
import { tmpdir } from "node:os";
|
|
@@ -27366,21 +28211,28 @@ function buildGenerateComponentsArgs(opts) {
|
|
|
27366
28211
|
if (opts.tokensPath) args.push("--tokens", opts.tokensPath);
|
|
27367
28212
|
if (opts.model) args.push("--model", opts.model);
|
|
27368
28213
|
if (opts.bedrock) args.push("--bedrock");
|
|
28214
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27369
28215
|
if (opts.generatePromptPath) args.push("--generate-prompt-path", opts.generatePromptPath);
|
|
27370
28216
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27371
28217
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
28218
|
+
if (opts.restoreCache) args.push("--restore-cache");
|
|
28219
|
+
if (opts.cachedComponents && opts.cachedComponents.length > 0) {
|
|
28220
|
+
args.push("--cached-components", JSON.stringify(opts.cachedComponents));
|
|
28221
|
+
}
|
|
27372
28222
|
return args;
|
|
27373
28223
|
}
|
|
27374
28224
|
function buildGenerateTokensArgs(opts) {
|
|
27375
28225
|
const args = [findCliPath(), "__generate", "tokens", "--agent", opts.agent, "--raw-tokens", opts.rawTokensPath];
|
|
27376
28226
|
if (opts.model) args.push("--model", opts.model);
|
|
27377
28227
|
if (opts.bedrock) args.push("--bedrock");
|
|
28228
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27378
28229
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27379
28230
|
return args;
|
|
27380
28231
|
}
|
|
27381
28232
|
function buildMapTokensArgs(opts) {
|
|
27382
28233
|
const args = ["map", "tokens", "--session", opts.sessionId, "--agent", opts.agent];
|
|
27383
28234
|
if (opts.model) args.push("--model", opts.model);
|
|
28235
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27384
28236
|
if (opts.skipAgent) args.push("--skip-agent");
|
|
27385
28237
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27386
28238
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
@@ -27472,6 +28324,7 @@ function WizardApp({
|
|
|
27472
28324
|
initialProjectPath,
|
|
27473
28325
|
host,
|
|
27474
28326
|
promptOverrides,
|
|
28327
|
+
noCache = false,
|
|
27475
28328
|
livePreview = true,
|
|
27476
28329
|
generatePromptPath,
|
|
27477
28330
|
skipMapTokens = false,
|
|
@@ -27496,6 +28349,7 @@ function WizardApp({
|
|
|
27496
28349
|
});
|
|
27497
28350
|
const allowEmptyDeleteAllRef = useRef10(false);
|
|
27498
28351
|
const generateChildRef = useRef10(null);
|
|
28352
|
+
const generationCachePreflightRef = useRef10(null);
|
|
27499
28353
|
const selectionToReviewStartedAtRef = useRef10(null);
|
|
27500
28354
|
const credentialsValidationIdRef = useRef10(0);
|
|
27501
28355
|
const pendingCredentialValidationRef = useRef10(null);
|
|
@@ -27510,8 +28364,9 @@ function WizardApp({
|
|
|
27510
28364
|
const existingEntitiesPromiseRef = useRef10(null);
|
|
27511
28365
|
const generatePromiseRef = useRef10(null);
|
|
27512
28366
|
const rawTokensEntryReady = !!initialRawTokensPath;
|
|
28367
|
+
const effectiveNoCache = resolveNoCacheForGenerate({ cliNoCache: noCache });
|
|
27513
28368
|
const initialStepResolved = rawTokensEntryReady ? initialProjectPath ? "path-validation" : "credentials" : initialProjectPath ? "token-input" : "welcome";
|
|
27514
|
-
const initialOutDir = initialProjectPath ? join23(
|
|
28369
|
+
const initialOutDir = initialProjectPath ? join23(resolve18(initialProjectPath), ".contentful") : "";
|
|
27515
28370
|
const [state, setState] = useState23({
|
|
27516
28371
|
step: initialStepResolved,
|
|
27517
28372
|
agent: initialAgent ?? "claude",
|
|
@@ -27687,13 +28542,14 @@ If you are using AWS Bedrock, run:
|
|
|
27687
28542
|
if (!deferStep) update({ step: nextStep });
|
|
27688
28543
|
return true;
|
|
27689
28544
|
};
|
|
27690
|
-
const runGenerateTokens = async (rawTokensPath, outDir) => {
|
|
28545
|
+
const runGenerateTokens = async (rawTokensPath, outDir, forceRegenerate = false) => {
|
|
27691
28546
|
update({ tokenGenerationStatus: "running" });
|
|
27692
28547
|
const tokenArgs = buildGenerateTokensArgs({
|
|
27693
28548
|
rawTokensPath,
|
|
27694
28549
|
agent: state.agent,
|
|
27695
28550
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27696
28551
|
...state.bedrock ? { bedrock: true } : {},
|
|
28552
|
+
noCache: effectiveNoCache || forceRegenerate,
|
|
27697
28553
|
promptOverrides
|
|
27698
28554
|
});
|
|
27699
28555
|
const result = await runSpawnedCli(tokenArgs);
|
|
@@ -27742,6 +28598,7 @@ If you are using AWS Bedrock, run:
|
|
|
27742
28598
|
const timer = startWizardTimer("token-mapping", {
|
|
27743
28599
|
sessionId: sessionId2,
|
|
27744
28600
|
silent,
|
|
28601
|
+
noCache: effectiveNoCache,
|
|
27745
28602
|
skipAgent: skipMapTokens
|
|
27746
28603
|
});
|
|
27747
28604
|
let mappablePropCount = 0;
|
|
@@ -27750,7 +28607,7 @@ If you are using AWS Bedrock, run:
|
|
|
27750
28607
|
const db = openPipelineDb();
|
|
27751
28608
|
try {
|
|
27752
28609
|
if (state.tokenSessionId && state.tokenSessionId !== sessionId2) {
|
|
27753
|
-
|
|
28610
|
+
copyTokensFromCache(db, state.tokenSessionId, sessionId2);
|
|
27754
28611
|
} else if (!state.tokenSessionId && state.tokensPath) {
|
|
27755
28612
|
const tokens = await readTokensFromPath("tokens", state.tokensPath);
|
|
27756
28613
|
storeDtcgTokens(db, sessionId2, [], tokens);
|
|
@@ -27790,6 +28647,7 @@ If you are using AWS Bedrock, run:
|
|
|
27790
28647
|
sessionId: sessionId2,
|
|
27791
28648
|
agent: state.agent,
|
|
27792
28649
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28650
|
+
noCache: effectiveNoCache,
|
|
27793
28651
|
skipAgent: skipMapTokens,
|
|
27794
28652
|
promptOverrides,
|
|
27795
28653
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
|
|
@@ -27869,7 +28727,7 @@ If you are using AWS Bedrock, run:
|
|
|
27869
28727
|
return promise;
|
|
27870
28728
|
};
|
|
27871
28729
|
const runExtract = async (projectPath, showProgress = true) => {
|
|
27872
|
-
const outDir = join23(
|
|
28730
|
+
const outDir = join23(resolve18(projectPath), ".contentful");
|
|
27873
28731
|
const existingEntitiesExpected = !state.credentialsSkipped && Boolean(state.spaceId && state.environmentId && state.cmaToken && projectPath);
|
|
27874
28732
|
update({
|
|
27875
28733
|
...showProgress ? { step: "extracting" } : {},
|
|
@@ -27884,6 +28742,7 @@ If you are using AWS Bedrock, run:
|
|
|
27884
28742
|
});
|
|
27885
28743
|
const existingEntitiesPromise = startExistingEntitiesFetch(projectPath, outDir);
|
|
27886
28744
|
const extractArgs = [findCliPath(), "__extract", "--project", projectPath];
|
|
28745
|
+
if (effectiveNoCache) extractArgs.push("--no-cache");
|
|
27887
28746
|
let selectionPromptText;
|
|
27888
28747
|
let selectionPromptPath;
|
|
27889
28748
|
try {
|
|
@@ -27892,7 +28751,7 @@ If you are using AWS Bedrock, run:
|
|
|
27892
28751
|
const selectOverride = overrides.get("select");
|
|
27893
28752
|
if (selectOverride?.kind === "text") selectionPromptText = selectOverride.value;
|
|
27894
28753
|
if (selectOverride?.kind === "path") {
|
|
27895
|
-
selectionPromptPath =
|
|
28754
|
+
selectionPromptPath = resolve18(selectOverride.value);
|
|
27896
28755
|
await resolvePromptOverride(selectOverride);
|
|
27897
28756
|
}
|
|
27898
28757
|
} catch (error) {
|
|
@@ -27916,7 +28775,8 @@ If you are using AWS Bedrock, run:
|
|
|
27916
28775
|
agent: state.agent,
|
|
27917
28776
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27918
28777
|
...selectionPromptText !== void 0 ? { promptText: selectionPromptText } : {},
|
|
27919
|
-
...selectionPromptPath ? { promptPath: selectionPromptPath } : {}
|
|
28778
|
+
...selectionPromptPath ? { promptPath: selectionPromptPath } : {},
|
|
28779
|
+
noCache: effectiveNoCache
|
|
27920
28780
|
});
|
|
27921
28781
|
})().catch((error) => {
|
|
27922
28782
|
selectionError = error;
|
|
@@ -28061,17 +28921,136 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28061
28921
|
generateProgress: null
|
|
28062
28922
|
}));
|
|
28063
28923
|
};
|
|
28064
|
-
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2) => ({
|
|
28924
|
+
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => ({
|
|
28065
28925
|
sessionId: extractSessionId,
|
|
28066
28926
|
tokensPath,
|
|
28067
28927
|
agent: state.agent,
|
|
28068
28928
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28069
28929
|
...state.bedrock ? { bedrock: true } : {},
|
|
28930
|
+
noCache: effectiveNoCache,
|
|
28070
28931
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {},
|
|
28071
28932
|
...generatePromptPath2 ? { generatePromptPath: generatePromptPath2 } : {},
|
|
28072
|
-
promptOverrides
|
|
28933
|
+
promptOverrides,
|
|
28934
|
+
...cachedComponents && cachedComponents.length > 0 ? { cachedComponents } : {}
|
|
28073
28935
|
});
|
|
28074
|
-
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2));
|
|
28936
|
+
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents));
|
|
28937
|
+
const buildGenerateCliArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateComponentsArgs(
|
|
28938
|
+
buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents)
|
|
28939
|
+
);
|
|
28940
|
+
const checkGenerateCache = async (extractSessionId, tokensPath) => {
|
|
28941
|
+
const timer = startWizardTimer("generation-cache-status", {
|
|
28942
|
+
sessionId: extractSessionId,
|
|
28943
|
+
noCache: effectiveNoCache
|
|
28944
|
+
});
|
|
28945
|
+
if (effectiveNoCache) {
|
|
28946
|
+
finishWizardTimer("generation-cache-status", timer, { status: "skipped" });
|
|
28947
|
+
return false;
|
|
28948
|
+
}
|
|
28949
|
+
const result = await runCli([...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"]);
|
|
28950
|
+
const hit = result.exitCode === 0 && /^cache-status=hit$/m.test(result.stdout);
|
|
28951
|
+
finishWizardTimer("generation-cache-status", timer, {
|
|
28952
|
+
status: hit ? "hit" : "miss",
|
|
28953
|
+
exitCode: result.exitCode,
|
|
28954
|
+
...result.exitCode !== 0 ? { stderrTail: result.stderr.trim().slice(-500) } : {}
|
|
28955
|
+
});
|
|
28956
|
+
return hit;
|
|
28957
|
+
};
|
|
28958
|
+
const checkGenerateCacheComponents = async (extractSessionId, tokensPath, restoreCache = false) => {
|
|
28959
|
+
const timer = startWizardTimer("generation-cache-components", {
|
|
28960
|
+
sessionId: extractSessionId,
|
|
28961
|
+
restoreCache,
|
|
28962
|
+
noCache: effectiveNoCache
|
|
28963
|
+
});
|
|
28964
|
+
if (effectiveNoCache) {
|
|
28965
|
+
finishWizardTimer("generation-cache-components", timer, { status: "skipped" });
|
|
28966
|
+
return /* @__PURE__ */ new Set();
|
|
28967
|
+
}
|
|
28968
|
+
const args = [...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"];
|
|
28969
|
+
if (restoreCache) args.push("--restore-cache");
|
|
28970
|
+
const result = await runCli(args);
|
|
28971
|
+
if (result.exitCode !== 0) {
|
|
28972
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28973
|
+
status: "error",
|
|
28974
|
+
exitCode: result.exitCode,
|
|
28975
|
+
stderrTail: result.stderr.trim().slice(-500)
|
|
28976
|
+
});
|
|
28977
|
+
return /* @__PURE__ */ new Set();
|
|
28978
|
+
}
|
|
28979
|
+
const line = /^cache-components=(.+)$/m.exec(result.stdout)?.[1];
|
|
28980
|
+
if (!line) {
|
|
28981
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28982
|
+
status: "missing-output",
|
|
28983
|
+
exitCode: result.exitCode,
|
|
28984
|
+
cachedCount: 0
|
|
28985
|
+
});
|
|
28986
|
+
return /* @__PURE__ */ new Set();
|
|
28987
|
+
}
|
|
28988
|
+
try {
|
|
28989
|
+
const names = JSON.parse(line);
|
|
28990
|
+
const cachedNames = new Set(
|
|
28991
|
+
Array.isArray(names) ? names.filter((name) => typeof name === "string") : []
|
|
28992
|
+
);
|
|
28993
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28994
|
+
status: "complete",
|
|
28995
|
+
exitCode: result.exitCode,
|
|
28996
|
+
cachedCount: cachedNames.size
|
|
28997
|
+
});
|
|
28998
|
+
return cachedNames;
|
|
28999
|
+
} catch {
|
|
29000
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
29001
|
+
status: "invalid-output",
|
|
29002
|
+
exitCode: result.exitCode,
|
|
29003
|
+
cachedCount: 0
|
|
29004
|
+
});
|
|
29005
|
+
return /* @__PURE__ */ new Set();
|
|
29006
|
+
}
|
|
29007
|
+
};
|
|
29008
|
+
useEffect15(() => {
|
|
29009
|
+
if (state.step !== "extracting" && state.step !== "scope-gate" || !state.extractSessionId || state.existingEntitiesStatus === "running" || state.existingEntitiesStatus === "idle" || state.selectionAgentStatus !== "complete" || state.compositionPhase !== "done" || state.rawTokensPath && state.tokenGenerationStatus !== "complete" || effectiveNoCache) {
|
|
29010
|
+
return;
|
|
29011
|
+
}
|
|
29012
|
+
const sessionId2 = state.extractSessionId;
|
|
29013
|
+
if (generationCachePreflightRef.current?.sessionId === sessionId2) return;
|
|
29014
|
+
const timer = startWizardTimer("generation-cache-preflight", { sessionId: sessionId2 });
|
|
29015
|
+
const db = openPipelineDb();
|
|
29016
|
+
let generatedNames = null;
|
|
29017
|
+
try {
|
|
29018
|
+
const rows = db.prepare("SELECT name, status FROM raw_components WHERE session_id = ?").all(sessionId2);
|
|
29019
|
+
if (rows.length > 0 && rows.every((row) => row.status === "generated")) {
|
|
29020
|
+
generatedNames = new Set(rows.map((row) => row.name));
|
|
29021
|
+
}
|
|
29022
|
+
} finally {
|
|
29023
|
+
db.close();
|
|
29024
|
+
}
|
|
29025
|
+
if (generatedNames) {
|
|
29026
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: Promise.resolve(generatedNames) };
|
|
29027
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29028
|
+
status: "complete",
|
|
29029
|
+
source: "session-db",
|
|
29030
|
+
cachedCount: generatedNames.size
|
|
29031
|
+
});
|
|
29032
|
+
return;
|
|
29033
|
+
}
|
|
29034
|
+
const promise = checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
29035
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise };
|
|
29036
|
+
void promise.then((cachedNames) => {
|
|
29037
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29038
|
+
status: "complete",
|
|
29039
|
+
source: "cache-status",
|
|
29040
|
+
cachedCount: cachedNames.size
|
|
29041
|
+
});
|
|
29042
|
+
});
|
|
29043
|
+
}, [
|
|
29044
|
+
state.step,
|
|
29045
|
+
state.extractSessionId,
|
|
29046
|
+
state.tokensPath,
|
|
29047
|
+
state.rawTokensPath,
|
|
29048
|
+
state.tokenGenerationStatus,
|
|
29049
|
+
state.selectionAgentStatus,
|
|
29050
|
+
state.compositionPhase,
|
|
29051
|
+
state.existingEntitiesStatus,
|
|
29052
|
+
state.existingEntitiesPath
|
|
29053
|
+
]);
|
|
28075
29054
|
const startGeneratePrefetch = (extractSessionId, tokensPath) => {
|
|
28076
29055
|
const args = buildGenerateArgs(extractSessionId, tokensPath);
|
|
28077
29056
|
let progressCursor = null;
|
|
@@ -28126,13 +29105,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28126
29105
|
});
|
|
28127
29106
|
return donePromise;
|
|
28128
29107
|
};
|
|
28129
|
-
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false) => {
|
|
29108
|
+
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false, cachedComponents = []) => {
|
|
28130
29109
|
const timer = startWizardTimer("component-generation", {
|
|
28131
29110
|
sessionId: extractSessionId,
|
|
28132
29111
|
acceptedCount,
|
|
28133
|
-
suppressScreen
|
|
29112
|
+
suppressScreen,
|
|
29113
|
+
noCache: effectiveNoCache
|
|
28134
29114
|
});
|
|
28135
|
-
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath);
|
|
29115
|
+
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath, cachedComponents);
|
|
28136
29116
|
let progressCursor = state.generateProgress;
|
|
28137
29117
|
const { donePromise } = spawnGenerateChild({
|
|
28138
29118
|
command: "node",
|
|
@@ -28202,6 +29182,25 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28202
29182
|
finishSelectionToReviewTimer("error");
|
|
28203
29183
|
}
|
|
28204
29184
|
};
|
|
29185
|
+
const finishCachedGeneration = async (sessionId2, acceptedCount) => {
|
|
29186
|
+
if (await runMapTokens2(sessionId2, true)) {
|
|
29187
|
+
finishSelectionToReviewTimer("cached");
|
|
29188
|
+
update(
|
|
29189
|
+
{
|
|
29190
|
+
acceptedCount,
|
|
29191
|
+
autoRejectedCount: 0,
|
|
29192
|
+
generateSessionId: sessionId2,
|
|
29193
|
+
generatedCount: acceptedCount,
|
|
29194
|
+
generateProgress: null,
|
|
29195
|
+
mapTokensStatus: "complete",
|
|
29196
|
+
step: "final-review"
|
|
29197
|
+
},
|
|
29198
|
+
{ clearScreen: false }
|
|
29199
|
+
);
|
|
29200
|
+
} else {
|
|
29201
|
+
finishSelectionToReviewTimer("error");
|
|
29202
|
+
}
|
|
29203
|
+
};
|
|
28205
29204
|
const advanceToPushFlow = (generatedAcceptedCount) => {
|
|
28206
29205
|
update({ generatedAcceptedCount });
|
|
28207
29206
|
void runSaveAndPush();
|
|
@@ -28386,8 +29385,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28386
29385
|
}
|
|
28387
29386
|
}
|
|
28388
29387
|
if (await runAgentAuthCheck("generating", true)) {
|
|
28389
|
-
|
|
28390
|
-
|
|
29388
|
+
const cacheHit = await checkGenerateCache(sid, state.tokensPath);
|
|
29389
|
+
if (cacheHit) {
|
|
29390
|
+
update({ step: "generating" });
|
|
29391
|
+
void finishCachedGeneration(sid, state.acceptedCount);
|
|
29392
|
+
} else {
|
|
29393
|
+
update({ step: "generating" });
|
|
29394
|
+
void runGenerate(sid, state.tokensPath, state.acceptedCount);
|
|
29395
|
+
}
|
|
28391
29396
|
}
|
|
28392
29397
|
return;
|
|
28393
29398
|
}
|
|
@@ -28751,7 +29756,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28751
29756
|
});
|
|
28752
29757
|
return { ok: false };
|
|
28753
29758
|
}
|
|
28754
|
-
await new Promise((
|
|
29759
|
+
await new Promise((resolve21) => setTimeout(resolve21, SAVE_CONFIRMATION_DELAY_MS));
|
|
28755
29760
|
update(nextStateAfterPrint({ skipGate: opts.skipGate, componentsPath }));
|
|
28756
29761
|
return { ok: true };
|
|
28757
29762
|
};
|
|
@@ -28828,6 +29833,12 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28828
29833
|
tokenReuseChecked.current = true;
|
|
28829
29834
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28830
29835
|
const existingTokensPath = join23(state.outDir, "tokens.json");
|
|
29836
|
+
if (effectiveNoCache) {
|
|
29837
|
+
tokenGenerationPromiseRef.current = runAgentAuthCheck(tokenNextStep).then(
|
|
29838
|
+
(ok2) => ok2 ? runGenerateTokens(state.rawTokensPath, state.outDir) : false
|
|
29839
|
+
);
|
|
29840
|
+
return;
|
|
29841
|
+
}
|
|
28831
29842
|
(async () => {
|
|
28832
29843
|
try {
|
|
28833
29844
|
await access7(existingTokensPath);
|
|
@@ -28911,7 +29922,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28911
29922
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28912
29923
|
update({ step: tokenNextStep });
|
|
28913
29924
|
if (await runAgentAuthCheck(tokenNextStep)) {
|
|
28914
|
-
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir);
|
|
29925
|
+
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir, true);
|
|
28915
29926
|
}
|
|
28916
29927
|
},
|
|
28917
29928
|
onQuit: () => process.exit(0)
|
|
@@ -29010,6 +30021,29 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
29010
30021
|
acceptedCount: decisions.accepted.length,
|
|
29011
30022
|
rejectedCount: decisions.rejected.length
|
|
29012
30023
|
}) : null;
|
|
30024
|
+
const preflight = generationCachePreflightRef.current;
|
|
30025
|
+
const cachePromise = preflight?.sessionId === sessionId2 ? preflight.promise : checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
30026
|
+
if (!preflight || preflight.sessionId !== sessionId2) {
|
|
30027
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: cachePromise };
|
|
30028
|
+
}
|
|
30029
|
+
const cacheWaitStartedAt = startWizardTimer("selection-cache-restoration-wait", {
|
|
30030
|
+
sessionId: sessionId2,
|
|
30031
|
+
preflight: Boolean(preflight?.sessionId === sessionId2)
|
|
30032
|
+
});
|
|
30033
|
+
try {
|
|
30034
|
+
const cachedNames = await cachePromise;
|
|
30035
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30036
|
+
status: "complete",
|
|
30037
|
+
cachedCount: cachedNames.size
|
|
30038
|
+
});
|
|
30039
|
+
} catch (error) {
|
|
30040
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30041
|
+
status: "error",
|
|
30042
|
+
error: error instanceof Error ? error.message : String(error)
|
|
30043
|
+
});
|
|
30044
|
+
finishSelectionToReviewTimer("error");
|
|
30045
|
+
throw error;
|
|
30046
|
+
}
|
|
29013
30047
|
await runScopeGate({
|
|
29014
30048
|
sessionId: sessionId2,
|
|
29015
30049
|
decisions,
|
|
@@ -29018,12 +30052,35 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
29018
30052
|
if (shouldGenerateAfterScopeGate({ acceptedCount })) {
|
|
29019
30053
|
const authPromise = runAgentAuthCheck("generating", true);
|
|
29020
30054
|
if (await authPromise) {
|
|
29021
|
-
|
|
29022
|
-
|
|
29023
|
-
|
|
29024
|
-
|
|
30055
|
+
const comparisonStartedAt = startWizardTimer("generation-cache-set-comparison", {
|
|
30056
|
+
sessionId: sid,
|
|
30057
|
+
acceptedCount: decisions?.accepted.length ?? 0
|
|
30058
|
+
});
|
|
30059
|
+
let cachedNames = await cachePromise;
|
|
30060
|
+
const acceptedNames = decisions?.accepted ?? [];
|
|
30061
|
+
let cacheHit = !effectiveNoCache && acceptedNames.length > 0 && acceptedNames.every((name) => cachedNames.has(name));
|
|
30062
|
+
if (!cacheHit && !effectiveNoCache && acceptedNames.length > 0) {
|
|
30063
|
+
cachedNames = await checkGenerateCacheComponents(sid, state.tokensPath, true);
|
|
30064
|
+
cacheHit = acceptedNames.every((name) => cachedNames.has(name));
|
|
30065
|
+
}
|
|
30066
|
+
finishWizardTimer("generation-cache-set-comparison", comparisonStartedAt, {
|
|
30067
|
+
status: "complete",
|
|
30068
|
+
cacheHit,
|
|
30069
|
+
cachedCount: cachedNames.size,
|
|
30070
|
+
acceptedCount: acceptedNames.length
|
|
29025
30071
|
});
|
|
29026
|
-
|
|
30072
|
+
if (cacheHit) {
|
|
30073
|
+
void finishCachedGeneration(sid, acceptedCount);
|
|
30074
|
+
} else {
|
|
30075
|
+
const acceptedNameSet = new Set(acceptedNames);
|
|
30076
|
+
const restoredCachedNames = [...cachedNames].filter((name) => acceptedNameSet.has(name));
|
|
30077
|
+
update({
|
|
30078
|
+
step: "generating",
|
|
30079
|
+
generateProgress: null,
|
|
30080
|
+
acceptedCount
|
|
30081
|
+
});
|
|
30082
|
+
void runGenerate(sid, state.tokensPath, acceptedCount, false, restoredCachedNames);
|
|
30083
|
+
}
|
|
29027
30084
|
} else {
|
|
29028
30085
|
finishSelectionToReviewTimer("error");
|
|
29029
30086
|
}
|
|
@@ -29389,7 +30446,7 @@ function registerImportCommand(program) {
|
|
|
29389
30446
|
"Override a composition, selection, token, generation, or token-mapping prompt (repeatable). value is a file path or literal text, e.g. --prompt select=./p.md",
|
|
29390
30447
|
(v, acc) => [...acc, v],
|
|
29391
30448
|
[]
|
|
29392
|
-
).action(async (opts) => {
|
|
30449
|
+
).option("--no-cache", "Re-run all steps even if output already exists").action(async (opts) => {
|
|
29393
30450
|
const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
|
|
29394
30451
|
if (opts.tokens !== void 0) {
|
|
29395
30452
|
const { access: access9 } = await import("node:fs/promises");
|
|
@@ -29426,6 +30483,7 @@ function registerImportCommand(program) {
|
|
|
29426
30483
|
...resolvedModel ? { initialModel: resolvedModel } : {},
|
|
29427
30484
|
initialProjectPath: opts.project !== "." ? normalizePath(opts.project) : void 0,
|
|
29428
30485
|
...buildCompositionForwardingOptions(opts),
|
|
30486
|
+
noCache: opts.cache === false,
|
|
29429
30487
|
skipMapTokens: false,
|
|
29430
30488
|
livePreview: true,
|
|
29431
30489
|
generatePromptPath: creds.generatePromptPath,
|
|
@@ -29513,7 +30571,7 @@ async function pathExists3(path) {
|
|
|
29513
30571
|
return access8(path).then(() => true).catch(() => false);
|
|
29514
30572
|
}
|
|
29515
30573
|
function runSpawn(cmd, args, opts = {}) {
|
|
29516
|
-
return new Promise((
|
|
30574
|
+
return new Promise((resolve21) => {
|
|
29517
30575
|
const child = spawn6(cmd, args, {
|
|
29518
30576
|
cwd: opts.cwd,
|
|
29519
30577
|
env: opts.env ?? process.env,
|
|
@@ -29525,7 +30583,7 @@ function runSpawn(cmd, args, opts = {}) {
|
|
|
29525
30583
|
const settle = (result) => {
|
|
29526
30584
|
if (settled) return;
|
|
29527
30585
|
settled = true;
|
|
29528
|
-
|
|
30586
|
+
resolve21(result);
|
|
29529
30587
|
};
|
|
29530
30588
|
child.on("error", (err) => settle({ exitCode: 1, stdout: "", stderr: err.message }));
|
|
29531
30589
|
child.stdout.on("data", (d) => {
|
|
@@ -30726,13 +31784,13 @@ function PrerequisitesScreen({
|
|
|
30726
31784
|
const driver = {
|
|
30727
31785
|
...base,
|
|
30728
31786
|
emit: (event) => setEvents((current) => [...current, event]),
|
|
30729
|
-
confirm: (question, defaultYes = true) => new Promise((
|
|
31787
|
+
confirm: (question, defaultYes = true) => new Promise((resolve21) => {
|
|
30730
31788
|
setConfirm({
|
|
30731
31789
|
question,
|
|
30732
31790
|
defaultYes,
|
|
30733
31791
|
resolve: (answer) => {
|
|
30734
31792
|
setConfirm(null);
|
|
30735
|
-
|
|
31793
|
+
resolve21(answer);
|
|
30736
31794
|
}
|
|
30737
31795
|
});
|
|
30738
31796
|
})
|
|
@@ -30807,8 +31865,8 @@ function SetupScreen({
|
|
|
30807
31865
|
useEffect21(() => {
|
|
30808
31866
|
if (startedRef.current) return;
|
|
30809
31867
|
startedRef.current = true;
|
|
30810
|
-
const runScreen = (build) => new Promise((
|
|
30811
|
-
setScreen(build(
|
|
31868
|
+
const runScreen = (build) => new Promise((resolve21) => {
|
|
31869
|
+
setScreen(build(resolve21));
|
|
30812
31870
|
});
|
|
30813
31871
|
void (async () => {
|
|
30814
31872
|
const results = [];
|
|
@@ -31416,8 +32474,11 @@ var init_source_call_site_evidence = __esm({
|
|
|
31416
32474
|
});
|
|
31417
32475
|
|
|
31418
32476
|
// packages/experience-design-system-cli-legacy/src/analyze/extract-command.ts
|
|
31419
|
-
import { mkdir as mkdir6, readdir as readdir3, readFile as
|
|
31420
|
-
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as
|
|
32477
|
+
import { mkdir as mkdir6, readdir as readdir3, readFile as readFile19, stat as stat6 } from "node:fs/promises";
|
|
32478
|
+
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as resolve19 } from "node:path";
|
|
32479
|
+
function resolveExtractNoCache(opts) {
|
|
32480
|
+
return opts.noCache === true || opts.cache === false;
|
|
32481
|
+
}
|
|
31421
32482
|
function isDenylistedNoiseFile(name) {
|
|
31422
32483
|
return DENYLISTED_EXACT_FILE_NAMES.has(name) || DENYLISTED_FILE_NAME_PATTERNS.some((pattern) => pattern.test(name));
|
|
31423
32484
|
}
|
|
@@ -31431,12 +32492,12 @@ async function retryDatabaseWrite(operation, attempts = 8) {
|
|
|
31431
32492
|
} catch (error) {
|
|
31432
32493
|
const message = error instanceof Error ? error.message : String(error);
|
|
31433
32494
|
if (!/database is locked|database is busy/i.test(message) || attempt >= attempts) throw error;
|
|
31434
|
-
await new Promise((
|
|
32495
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(250 * attempt, 2e3)));
|
|
31435
32496
|
}
|
|
31436
32497
|
}
|
|
31437
32498
|
}
|
|
31438
32499
|
function resolveFromProjectRoot(projectRoot, inputPath) {
|
|
31439
|
-
return isAbsolute2(inputPath) ? inputPath :
|
|
32500
|
+
return isAbsolute2(inputPath) ? inputPath : resolve19(projectRoot, inputPath);
|
|
31440
32501
|
}
|
|
31441
32502
|
async function pathExists4(path) {
|
|
31442
32503
|
return Boolean(await stat6(path).catch(() => null));
|
|
@@ -31483,7 +32544,7 @@ async function readCandidateFiles(components, extraFiles = []) {
|
|
|
31483
32544
|
await Promise.all(
|
|
31484
32545
|
[...paths].map(async (p) => {
|
|
31485
32546
|
try {
|
|
31486
|
-
const content = await
|
|
32547
|
+
const content = await readFile19(p, "utf8");
|
|
31487
32548
|
out.push({ path: p, content });
|
|
31488
32549
|
} catch {
|
|
31489
32550
|
}
|
|
@@ -31496,7 +32557,8 @@ function registerInternalExtractCommand(program) {
|
|
|
31496
32557
|
"--resolve-unreachable <mode>",
|
|
31497
32558
|
"Retry pass for unresolved Svelte Props types: 'auto' (default), 'always', or 'never'",
|
|
31498
32559
|
"auto"
|
|
31499
|
-
).action(async (opts) => {
|
|
32560
|
+
).option("--no-cache", "Re-run extraction even when all source files are unchanged").action(async (opts) => {
|
|
32561
|
+
const noCache = resolveExtractNoCache(opts);
|
|
31500
32562
|
const resolveUnreachable = (() => {
|
|
31501
32563
|
const v = opts.resolveUnreachable ?? "auto";
|
|
31502
32564
|
if (v !== "auto" && v !== "always" && v !== "never") {
|
|
@@ -31506,7 +32568,7 @@ function registerInternalExtractCommand(program) {
|
|
|
31506
32568
|
}
|
|
31507
32569
|
return v;
|
|
31508
32570
|
})();
|
|
31509
|
-
const projectRoot =
|
|
32571
|
+
const projectRoot = resolve19(opts.project);
|
|
31510
32572
|
const outDir = join27(projectRoot, ".contentful");
|
|
31511
32573
|
let sourceDirectory;
|
|
31512
32574
|
if (opts.dir !== void 0) {
|
|
@@ -31530,16 +32592,50 @@ function registerInternalExtractCommand(program) {
|
|
|
31530
32592
|
process.stderr.write(`progress=scan-done:${sourceFiles.length}
|
|
31531
32593
|
`);
|
|
31532
32594
|
}
|
|
31533
|
-
const
|
|
31534
|
-
|
|
31535
|
-
|
|
32595
|
+
const extractionCacheDb = openPipelineDb();
|
|
32596
|
+
let extraction;
|
|
32597
|
+
let extractionCacheHits = 0;
|
|
32598
|
+
try {
|
|
32599
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32600
|
+
const cachedByPath = /* @__PURE__ */ new Map();
|
|
32601
|
+
if (!noCache && sourceFiles.length > 0) {
|
|
32602
|
+
const hashes = await Promise.all(
|
|
32603
|
+
sourceFiles.map(async (filePath) => [filePath, await hashFile(filePath)])
|
|
32604
|
+
);
|
|
32605
|
+
for (const [filePath, fileHash] of hashes) {
|
|
32606
|
+
cachedByPath.set(filePath, lookupExtractCache(extractionCacheDb, fileHash, cacheVersion));
|
|
32607
|
+
}
|
|
32608
|
+
}
|
|
32609
|
+
const allFilesCached = !noCache && sourceFiles.length > 0 && sourceFiles.every((filePath) => cachedByPath.get(filePath) !== null);
|
|
32610
|
+
if (allFilesCached) {
|
|
32611
|
+
const cachedComponents = sourceFiles.flatMap((filePath) => cachedByPath.get(filePath).components);
|
|
32612
|
+
extractionCacheHits = sourceFiles.length;
|
|
32613
|
+
extraction = { components: cachedComponents, warnings: [], exclusions: [] };
|
|
31536
32614
|
if (!process.stdout.isTTY) {
|
|
31537
|
-
process.stderr.write(
|
|
31538
|
-
`
|
|
32615
|
+
process.stderr.write(
|
|
32616
|
+
`progress=extract:${sourceFiles.length}/${sourceFiles.length}:${cachedComponents.length}
|
|
32617
|
+
`
|
|
32618
|
+
);
|
|
31539
32619
|
}
|
|
31540
|
-
|
|
31541
|
-
|
|
31542
|
-
|
|
32620
|
+
getDebugLogger().event("analyze", "extract.cache-hit", {
|
|
32621
|
+
files: sourceFiles.length,
|
|
32622
|
+
components: cachedComponents.length
|
|
32623
|
+
});
|
|
32624
|
+
} else {
|
|
32625
|
+
extraction = await extractComponents(
|
|
32626
|
+
sourceFiles,
|
|
32627
|
+
({ filesProcessed, componentsFound }) => {
|
|
32628
|
+
if (!process.stdout.isTTY) {
|
|
32629
|
+
process.stderr.write(`progress=extract:${filesProcessed}/${sourceFiles.length}:${componentsFound}
|
|
32630
|
+
`);
|
|
32631
|
+
}
|
|
32632
|
+
},
|
|
32633
|
+
{ resolveUnreachable, projectRoot }
|
|
32634
|
+
);
|
|
32635
|
+
}
|
|
32636
|
+
} finally {
|
|
32637
|
+
extractionCacheDb.close();
|
|
32638
|
+
}
|
|
31543
32639
|
await mkdir6(outDir, { recursive: true });
|
|
31544
32640
|
const db = openPipelineDb();
|
|
31545
32641
|
const { sessionId: sessionId2 } = getOrCreateSession(db, void 0, void 0, {
|
|
@@ -31554,6 +32650,25 @@ function registerInternalExtractCommand(program) {
|
|
|
31554
32650
|
const stepId = createStep(db, sessionId2, "analyze extract", {
|
|
31555
32651
|
project: projectRoot
|
|
31556
32652
|
});
|
|
32653
|
+
if (extractionCacheHits === 0 && !noCache) {
|
|
32654
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32655
|
+
const componentsBySourcePath = /* @__PURE__ */ new Map();
|
|
32656
|
+
for (const component of extraction.components) {
|
|
32657
|
+
if (!component.sourcePath) continue;
|
|
32658
|
+
const components = componentsBySourcePath.get(component.sourcePath) ?? [];
|
|
32659
|
+
components.push(component);
|
|
32660
|
+
componentsBySourcePath.set(component.sourcePath, components);
|
|
32661
|
+
}
|
|
32662
|
+
for (const filePath of sourceFiles) {
|
|
32663
|
+
storeExtractCache(
|
|
32664
|
+
db,
|
|
32665
|
+
filePath,
|
|
32666
|
+
await hashFile(filePath),
|
|
32667
|
+
cacheVersion,
|
|
32668
|
+
componentsBySourcePath.get(filePath) ?? []
|
|
32669
|
+
);
|
|
32670
|
+
}
|
|
32671
|
+
}
|
|
31557
32672
|
const classifiedComponents = extraction.components.map(preClassifyComponent);
|
|
31558
32673
|
for (const exclusion of extraction.exclusions ?? []) {
|
|
31559
32674
|
getDebugLogger().event("filter", "extract.excluded", { ...exclusion });
|
|
@@ -31658,6 +32773,7 @@ var init_extract_command = __esm({
|
|
|
31658
32773
|
"use strict";
|
|
31659
32774
|
init_src2();
|
|
31660
32775
|
init_db();
|
|
32776
|
+
init_cache_keys();
|
|
31661
32777
|
init_cycle_detection();
|
|
31662
32778
|
init_resolve_mapping();
|
|
31663
32779
|
init_manifest_doc_evidence();
|
|
@@ -31756,7 +32872,7 @@ __export(program_exports, {
|
|
|
31756
32872
|
});
|
|
31757
32873
|
import { spawn as spawn7 } from "node:child_process";
|
|
31758
32874
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
31759
|
-
import { dirname as dirname18, join as join28, resolve as
|
|
32875
|
+
import { dirname as dirname18, join as join28, resolve as resolve20 } from "node:path";
|
|
31760
32876
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
31761
32877
|
import { Command } from "commander";
|
|
31762
32878
|
async function runBuild(opts) {
|
|
@@ -31786,7 +32902,7 @@ function resolveBedrockFromAncestors(actionCommand) {
|
|
|
31786
32902
|
}
|
|
31787
32903
|
function registerBuildCommand(program) {
|
|
31788
32904
|
program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").helpOption(false).action(async () => {
|
|
31789
|
-
const pkgRoot =
|
|
32905
|
+
const pkgRoot = resolve20(dirname18(fileURLToPath3(import.meta.url)), "..", "..");
|
|
31790
32906
|
process.stderr.write("\u2699 Building from source...\n");
|
|
31791
32907
|
const { exitCode } = await runBuild({
|
|
31792
32908
|
spawnFn: () => spawn7("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|