@contentful/experience-design-system-cli 2.35.1-dev-build-a2149178.0 → 2.35.1-dev-build-36aa669d.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 +1329 -213
- 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";
|
|
@@ -10308,6 +10365,41 @@ var init_read3 = __esm({
|
|
|
10308
10365
|
}
|
|
10309
10366
|
});
|
|
10310
10367
|
|
|
10368
|
+
// packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts
|
|
10369
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
10370
|
+
function hashComponentShape(component) {
|
|
10371
|
+
const payload = {
|
|
10372
|
+
framework: component.framework,
|
|
10373
|
+
name: component.name,
|
|
10374
|
+
source: component.source,
|
|
10375
|
+
props: component.props.map((p) => ({
|
|
10376
|
+
name: p.name,
|
|
10377
|
+
type: p.type
|
|
10378
|
+
})),
|
|
10379
|
+
slots: component.slots.map((s) => ({
|
|
10380
|
+
name: s.name,
|
|
10381
|
+
isDefault: s.isDefault
|
|
10382
|
+
}))
|
|
10383
|
+
};
|
|
10384
|
+
return createHash2("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
10385
|
+
}
|
|
10386
|
+
var init_hash_component_shape = __esm({
|
|
10387
|
+
"packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts"() {
|
|
10388
|
+
"use strict";
|
|
10389
|
+
}
|
|
10390
|
+
});
|
|
10391
|
+
|
|
10392
|
+
// packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts
|
|
10393
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
10394
|
+
function hashTokenContent(rawTokenContent) {
|
|
10395
|
+
return createHash3("sha256").update(rawTokenContent.trim()).digest("hex");
|
|
10396
|
+
}
|
|
10397
|
+
var init_hash_token_content = __esm({
|
|
10398
|
+
"packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts"() {
|
|
10399
|
+
"use strict";
|
|
10400
|
+
}
|
|
10401
|
+
});
|
|
10402
|
+
|
|
10311
10403
|
// packages/experience-design-system-cli-legacy/src/session/repositories/tokens/write.ts
|
|
10312
10404
|
function deleteRawTokensForSession(db, sessionId2) {
|
|
10313
10405
|
db.prepare("DELETE FROM raw_token_groups WHERE session_id = ?").run(sessionId2);
|
|
@@ -10471,17 +10563,47 @@ var init_replace_raw_prop_token_paths = __esm({
|
|
|
10471
10563
|
}
|
|
10472
10564
|
});
|
|
10473
10565
|
|
|
10566
|
+
// packages/experience-design-system-cli-legacy/src/session/cache-keys.ts
|
|
10567
|
+
var cache_keys_exports = {};
|
|
10568
|
+
__export(cache_keys_exports, {
|
|
10569
|
+
hashContent: () => hashContent,
|
|
10570
|
+
hashFile: () => hashFile,
|
|
10571
|
+
hashPromptForSkill: () => hashPromptForSkill
|
|
10572
|
+
});
|
|
10573
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
10574
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
10575
|
+
import { resolve as resolve8 } from "node:path";
|
|
10576
|
+
function hashContent(content) {
|
|
10577
|
+
return createHash4("sha256").update(content).digest("hex");
|
|
10578
|
+
}
|
|
10579
|
+
async function hashFile(filePath) {
|
|
10580
|
+
const content = await readFile7(filePath, "utf8");
|
|
10581
|
+
return hashContent(content);
|
|
10582
|
+
}
|
|
10583
|
+
async function hashPromptForSkill(skill, agent, model, skillPathOverride, extraInputs = [], skillContentOverride) {
|
|
10584
|
+
const promptHash = skillContentOverride ? hashContent(skillContentOverride) : skillPathOverride ? await hashFile(resolve8(skillPathOverride)) : await hashFile(resolveSkillPath(skill));
|
|
10585
|
+
const extraSegment = extraInputs.length > 0 ? `|${extraInputs.join("|")}` : "";
|
|
10586
|
+
return hashContent(`${promptHash}|${agent}|${model ?? ""}${extraSegment}`);
|
|
10587
|
+
}
|
|
10588
|
+
var init_cache_keys = __esm({
|
|
10589
|
+
"packages/experience-design-system-cli-legacy/src/session/cache-keys.ts"() {
|
|
10590
|
+
"use strict";
|
|
10591
|
+
init_src();
|
|
10592
|
+
}
|
|
10593
|
+
});
|
|
10594
|
+
|
|
10474
10595
|
// packages/experience-design-system-cli-legacy/src/session/db.ts
|
|
10475
10596
|
import { DatabaseSync } from "node:sqlite";
|
|
10476
10597
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
10477
|
-
import { readFile as
|
|
10598
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
10599
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
10478
10600
|
import { homedir as homedir3 } from "node:os";
|
|
10479
|
-
import { dirname as dirname14, resolve as
|
|
10601
|
+
import { dirname as dirname14, resolve as resolve9 } from "node:path";
|
|
10480
10602
|
function getPipelineDbPath() {
|
|
10481
10603
|
if (process.env.EDS_PIPELINE_DB_PATH) {
|
|
10482
|
-
return
|
|
10604
|
+
return resolve9(process.env.EDS_PIPELINE_DB_PATH);
|
|
10483
10605
|
}
|
|
10484
|
-
return
|
|
10606
|
+
return resolve9(homedir3(), ".contentful", "experience-design-system-cli", "pipeline.db");
|
|
10485
10607
|
}
|
|
10486
10608
|
function openPipelineDb(dbPath) {
|
|
10487
10609
|
const path = dbPath ?? getPipelineDbPath();
|
|
@@ -10615,8 +10737,134 @@ function applyDbMigrations(db) {
|
|
|
10615
10737
|
if (!rawSlotColsForRationale.some((c2) => c2.name === "rationale")) {
|
|
10616
10738
|
db.exec("ALTER TABLE raw_slots ADD COLUMN rationale TEXT");
|
|
10617
10739
|
}
|
|
10618
|
-
|
|
10619
|
-
|
|
10740
|
+
const hasExtractCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='extract_cache'`).all();
|
|
10741
|
+
if (hasExtractCache.length === 0) {
|
|
10742
|
+
db.exec(`
|
|
10743
|
+
CREATE TABLE extract_cache (
|
|
10744
|
+
file_path TEXT NOT NULL,
|
|
10745
|
+
file_hash TEXT NOT NULL,
|
|
10746
|
+
cli_version TEXT NOT NULL,
|
|
10747
|
+
created_at TEXT NOT NULL,
|
|
10748
|
+
updated_at TEXT NOT NULL,
|
|
10749
|
+
components_json TEXT NOT NULL,
|
|
10750
|
+
PRIMARY KEY (file_hash, cli_version)
|
|
10751
|
+
);
|
|
10752
|
+
CREATE INDEX idx_extract_cache_file ON extract_cache(file_path);
|
|
10753
|
+
`);
|
|
10754
|
+
}
|
|
10755
|
+
const hasSelectCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='select_cache'`).all();
|
|
10756
|
+
if (hasSelectCache.length === 0) {
|
|
10757
|
+
db.exec(`
|
|
10758
|
+
CREATE TABLE select_cache (
|
|
10759
|
+
component_hash TEXT NOT NULL,
|
|
10760
|
+
prompt_hash TEXT NOT NULL,
|
|
10761
|
+
cli_version TEXT NOT NULL,
|
|
10762
|
+
decision TEXT NOT NULL CHECK (decision IN ('accepted','rejected')),
|
|
10763
|
+
reason TEXT,
|
|
10764
|
+
created_at TEXT NOT NULL,
|
|
10765
|
+
updated_at TEXT NOT NULL,
|
|
10766
|
+
PRIMARY KEY (component_hash, prompt_hash, cli_version)
|
|
10767
|
+
);
|
|
10768
|
+
`);
|
|
10769
|
+
}
|
|
10770
|
+
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='generation_cache'`).all();
|
|
10771
|
+
if (tables.length === 0) {
|
|
10772
|
+
db.exec(`
|
|
10773
|
+
CREATE TABLE generation_cache (
|
|
10774
|
+
input_hash TEXT NOT NULL,
|
|
10775
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10776
|
+
entity_id TEXT NOT NULL,
|
|
10777
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10778
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10779
|
+
created_at TEXT NOT NULL,
|
|
10780
|
+
updated_at TEXT NOT NULL,
|
|
10781
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
10782
|
+
);
|
|
10783
|
+
CREATE INDEX idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10784
|
+
CREATE INDEX idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10785
|
+
`);
|
|
10786
|
+
}
|
|
10787
|
+
const genCacheCols = db.prepare(`PRAGMA table_info(generation_cache)`).all();
|
|
10788
|
+
const hasPromptHash = genCacheCols.some((c2) => c2.name === "prompt_hash");
|
|
10789
|
+
const oldPkCols = genCacheCols.filter((c2) => c2.pk > 0).map((c2) => c2.name);
|
|
10790
|
+
const promptHashInPk = oldPkCols.includes("prompt_hash");
|
|
10791
|
+
if (!hasPromptHash) {
|
|
10792
|
+
db.exec(`ALTER TABLE generation_cache ADD COLUMN prompt_hash TEXT NOT NULL DEFAULT ''`);
|
|
10793
|
+
}
|
|
10794
|
+
if (!promptHashInPk) {
|
|
10795
|
+
db.exec("BEGIN");
|
|
10796
|
+
try {
|
|
10797
|
+
db.exec(`
|
|
10798
|
+
CREATE TABLE generation_cache__new (
|
|
10799
|
+
input_hash TEXT NOT NULL,
|
|
10800
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10801
|
+
entity_id TEXT NOT NULL,
|
|
10802
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10803
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10804
|
+
created_at TEXT NOT NULL,
|
|
10805
|
+
updated_at TEXT NOT NULL,
|
|
10806
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10807
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10808
|
+
);
|
|
10809
|
+
INSERT INTO generation_cache__new
|
|
10810
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10811
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10812
|
+
FROM generation_cache;
|
|
10813
|
+
DROP TABLE generation_cache;
|
|
10814
|
+
ALTER TABLE generation_cache__new RENAME TO generation_cache;
|
|
10815
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10816
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10817
|
+
`);
|
|
10818
|
+
db.exec("COMMIT");
|
|
10819
|
+
} catch (e) {
|
|
10820
|
+
db.exec("ROLLBACK");
|
|
10821
|
+
throw e;
|
|
10822
|
+
}
|
|
10823
|
+
}
|
|
10824
|
+
const genCacheTableSql = db.prepare(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'generation_cache'`).get();
|
|
10825
|
+
const hasTokenMappingEntityType = genCacheTableSql?.sql.includes("'token_mapping'") ?? true;
|
|
10826
|
+
if (!hasTokenMappingEntityType) {
|
|
10827
|
+
db.exec("BEGIN");
|
|
10828
|
+
try {
|
|
10829
|
+
db.exec(`
|
|
10830
|
+
CREATE TABLE generation_cache__new2 (
|
|
10831
|
+
input_hash TEXT NOT NULL,
|
|
10832
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10833
|
+
entity_id TEXT NOT NULL,
|
|
10834
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10835
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10836
|
+
created_at TEXT NOT NULL,
|
|
10837
|
+
updated_at TEXT NOT NULL,
|
|
10838
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10839
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10840
|
+
);
|
|
10841
|
+
INSERT INTO generation_cache__new2
|
|
10842
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10843
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10844
|
+
FROM generation_cache;
|
|
10845
|
+
DROP TABLE generation_cache;
|
|
10846
|
+
ALTER TABLE generation_cache__new2 RENAME TO generation_cache;
|
|
10847
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10848
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10849
|
+
`);
|
|
10850
|
+
db.exec("COMMIT");
|
|
10851
|
+
} catch (e) {
|
|
10852
|
+
db.exec("ROLLBACK");
|
|
10853
|
+
throw e;
|
|
10854
|
+
}
|
|
10855
|
+
}
|
|
10856
|
+
const hasCompositionCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='composition_cache'`).all();
|
|
10857
|
+
if (hasCompositionCache.length === 0) {
|
|
10858
|
+
db.exec(`
|
|
10859
|
+
CREATE TABLE composition_cache (
|
|
10860
|
+
input_hash TEXT NOT NULL,
|
|
10861
|
+
cli_version TEXT NOT NULL,
|
|
10862
|
+
agent_output TEXT NOT NULL,
|
|
10863
|
+
created_at TEXT NOT NULL,
|
|
10864
|
+
updated_at TEXT NOT NULL,
|
|
10865
|
+
PRIMARY KEY (input_hash, cli_version)
|
|
10866
|
+
);
|
|
10867
|
+
`);
|
|
10620
10868
|
}
|
|
10621
10869
|
}
|
|
10622
10870
|
function loadComponentReviewMetadata(db, sessionId2, componentName) {
|
|
@@ -11156,16 +11404,16 @@ function extractRelativeImportPaths(sourceText) {
|
|
|
11156
11404
|
return [...specifiers];
|
|
11157
11405
|
}
|
|
11158
11406
|
async function resolveRelativeImport(specifier, fromDir) {
|
|
11159
|
-
const basePath =
|
|
11407
|
+
const basePath = resolve9(fromDir, specifier);
|
|
11160
11408
|
const candidates = [
|
|
11161
11409
|
basePath,
|
|
11162
11410
|
...rewrittenSourcePaths(basePath),
|
|
11163
11411
|
...SIBLING_FILE_EXTENSIONS.map((ext) => `${basePath}${ext}`),
|
|
11164
|
-
...SIBLING_FILE_EXTENSIONS.map((ext) =>
|
|
11412
|
+
...SIBLING_FILE_EXTENSIONS.map((ext) => resolve9(basePath, `index${ext}`))
|
|
11165
11413
|
];
|
|
11166
11414
|
for (const candidate of candidates) {
|
|
11167
11415
|
try {
|
|
11168
|
-
await
|
|
11416
|
+
await readFile8(candidate, "utf8");
|
|
11169
11417
|
return candidate;
|
|
11170
11418
|
} catch {
|
|
11171
11419
|
}
|
|
@@ -11181,7 +11429,7 @@ async function resolveImportSpecifiers(sourceText, fromDir) {
|
|
|
11181
11429
|
return resolvedPaths;
|
|
11182
11430
|
}
|
|
11183
11431
|
async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateTypeNames = []) {
|
|
11184
|
-
const visited = /* @__PURE__ */ new Set([
|
|
11432
|
+
const visited = /* @__PURE__ */ new Set([resolve9(sourcePath)]);
|
|
11185
11433
|
const discovered = [];
|
|
11186
11434
|
let frontier = [{ text: sourceText, dir: dirname14(sourcePath) }];
|
|
11187
11435
|
for (let hop = 0; hop < MAX_SIBLING_DEPTH && discovered.length < MAX_SIBLING_CANDIDATES_EXPLORED; hop++) {
|
|
@@ -11195,7 +11443,7 @@ async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateType
|
|
|
11195
11443
|
if (discovered.length >= MAX_SIBLING_CANDIDATES_EXPLORED) break;
|
|
11196
11444
|
let content;
|
|
11197
11445
|
try {
|
|
11198
|
-
content = await
|
|
11446
|
+
content = await readFile8(resolvedPath, "utf8");
|
|
11199
11447
|
} catch {
|
|
11200
11448
|
continue;
|
|
11201
11449
|
}
|
|
@@ -11232,7 +11480,7 @@ async function loadComponentSourceRef(name, sourcePath, propNames = [], propType
|
|
|
11232
11480
|
let truncatedSiblingCount = 0;
|
|
11233
11481
|
const usesNotShown = /* @__PURE__ */ new Set();
|
|
11234
11482
|
try {
|
|
11235
|
-
const rawText = await
|
|
11483
|
+
const rawText = await readFile8(sourcePath, "utf8");
|
|
11236
11484
|
let siblingUsesNotShown;
|
|
11237
11485
|
let declaredTypeNames;
|
|
11238
11486
|
({
|
|
@@ -11668,6 +11916,108 @@ function backfillUnclassifiedProps(db, sessionId2) {
|
|
|
11668
11916
|
).run(sessionId2, sessionId2);
|
|
11669
11917
|
return Number(withCategory.changes) + Number(withoutCategory.changes);
|
|
11670
11918
|
}
|
|
11919
|
+
function computeMapTokensInputHash(db, sessionId2, componentSourceRefs = []) {
|
|
11920
|
+
const props = db.prepare(
|
|
11921
|
+
`SELECT rc.name AS component_name, rp.name AS prop_name, rp.cdf_token_kind, rp.default_value
|
|
11922
|
+
FROM raw_props rp
|
|
11923
|
+
JOIN raw_components rc ON rc.session_id = rp.session_id AND rc.component_id = rp.component_id
|
|
11924
|
+
WHERE rp.session_id = ? AND rp.cdf_type = 'token' AND rp.cdf_category = 'design'
|
|
11925
|
+
ORDER BY rc.name, rp.name`
|
|
11926
|
+
).all(sessionId2);
|
|
11927
|
+
const tokens = db.prepare(`SELECT path, type FROM raw_tokens WHERE session_id = ? ORDER BY path`).all(sessionId2);
|
|
11928
|
+
const defaultMappings = db.prepare("SELECT raw_name, path, source FROM raw_token_name_paths WHERE session_id = ? ORDER BY raw_name").all(sessionId2);
|
|
11929
|
+
const payload = {
|
|
11930
|
+
props: props.map((p) => ({
|
|
11931
|
+
component: p.component_name,
|
|
11932
|
+
prop: p.prop_name,
|
|
11933
|
+
tokenKind: p.cdf_token_kind,
|
|
11934
|
+
rawDefault: p.default_value
|
|
11935
|
+
})),
|
|
11936
|
+
tokens,
|
|
11937
|
+
defaultMappings,
|
|
11938
|
+
// The agent's evidence, not just its inputs: a comment or allowlist edit
|
|
11939
|
+
// in a source file (or a sibling it reads) changes the correct answer
|
|
11940
|
+
// without touching props or tokens, so it must invalidate the cache too.
|
|
11941
|
+
sourceRefs: [...componentSourceRefs].sort((a, b) => a.component.localeCompare(b.component)).map((ref) => ({
|
|
11942
|
+
component: ref.component,
|
|
11943
|
+
content: ref.content,
|
|
11944
|
+
siblingFiles: (ref.siblingFiles ?? []).map((s) => ({ path: s.path, content: s.content })).sort((a, b) => a.path.localeCompare(b.path)),
|
|
11945
|
+
usesNotShown: [...ref.usesNotShown ?? []].sort()
|
|
11946
|
+
}))
|
|
11947
|
+
};
|
|
11948
|
+
return createHash5("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
11949
|
+
}
|
|
11950
|
+
function lookupCache(db, inputHash, entityType, entityId, promptHash = "") {
|
|
11951
|
+
const row = db.prepare(
|
|
11952
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11953
|
+
FROM generation_cache
|
|
11954
|
+
WHERE input_hash = ? AND entity_type = ? AND entity_id = ? AND prompt_hash = ?`
|
|
11955
|
+
).get(inputHash, entityType, entityId, promptHash);
|
|
11956
|
+
if (!row) return null;
|
|
11957
|
+
return {
|
|
11958
|
+
inputHash: row.input_hash,
|
|
11959
|
+
entityType: row.entity_type,
|
|
11960
|
+
entityId: row.entity_id,
|
|
11961
|
+
sourceSessionId: row.source_session_id,
|
|
11962
|
+
humanEdited: row.human_edited === 1,
|
|
11963
|
+
promptHash: row.prompt_hash,
|
|
11964
|
+
createdAt: row.created_at,
|
|
11965
|
+
updatedAt: row.updated_at
|
|
11966
|
+
};
|
|
11967
|
+
}
|
|
11968
|
+
function lookupCacheByEntity(db, entityType, entityId) {
|
|
11969
|
+
const row = db.prepare(
|
|
11970
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11971
|
+
FROM generation_cache
|
|
11972
|
+
WHERE entity_type = ? AND entity_id = ?
|
|
11973
|
+
ORDER BY updated_at DESC LIMIT 1`
|
|
11974
|
+
).get(entityType, entityId);
|
|
11975
|
+
if (!row) return null;
|
|
11976
|
+
return {
|
|
11977
|
+
inputHash: row.input_hash,
|
|
11978
|
+
entityType: row.entity_type,
|
|
11979
|
+
entityId: row.entity_id,
|
|
11980
|
+
sourceSessionId: row.source_session_id,
|
|
11981
|
+
humanEdited: row.human_edited === 1,
|
|
11982
|
+
promptHash: row.prompt_hash,
|
|
11983
|
+
createdAt: row.created_at,
|
|
11984
|
+
updatedAt: row.updated_at
|
|
11985
|
+
};
|
|
11986
|
+
}
|
|
11987
|
+
function storeCache(db, inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash = "") {
|
|
11988
|
+
storeCaches(db, [{ inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash }]);
|
|
11989
|
+
}
|
|
11990
|
+
function storeCaches(db, entries) {
|
|
11991
|
+
if (entries.length === 0) return;
|
|
11992
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11993
|
+
const insert = db.prepare(
|
|
11994
|
+
`INSERT INTO generation_cache (input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
11995
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
11996
|
+
ON CONFLICT(input_hash, prompt_hash, entity_type, entity_id) DO UPDATE SET
|
|
11997
|
+
source_session_id = excluded.source_session_id,
|
|
11998
|
+
human_edited = CASE WHEN generation_cache.human_edited = 1 THEN 1 ELSE excluded.human_edited END,
|
|
11999
|
+
updated_at = excluded.updated_at`
|
|
12000
|
+
);
|
|
12001
|
+
db.exec("BEGIN");
|
|
12002
|
+
try {
|
|
12003
|
+
for (const entry of entries) {
|
|
12004
|
+
insert.run(
|
|
12005
|
+
entry.inputHash,
|
|
12006
|
+
entry.entityType,
|
|
12007
|
+
entry.entityId,
|
|
12008
|
+
entry.sourceSessionId,
|
|
12009
|
+
entry.humanEdited ? 1 : 0,
|
|
12010
|
+
now,
|
|
12011
|
+
now,
|
|
12012
|
+
entry.promptHash ?? ""
|
|
12013
|
+
);
|
|
12014
|
+
}
|
|
12015
|
+
db.exec("COMMIT");
|
|
12016
|
+
} catch (e) {
|
|
12017
|
+
db.exec("ROLLBACK");
|
|
12018
|
+
throw e;
|
|
12019
|
+
}
|
|
12020
|
+
}
|
|
11671
12021
|
function storeScannedFiles(db, sessionId2, filePaths) {
|
|
11672
12022
|
db.exec("BEGIN");
|
|
11673
12023
|
try {
|
|
@@ -11750,7 +12100,105 @@ function filterUnknownSlotAllowedComponents(db, sessionId2, allowedComponentName
|
|
|
11750
12100
|
}
|
|
11751
12101
|
return unknown;
|
|
11752
12102
|
}
|
|
11753
|
-
function
|
|
12103
|
+
function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentId, manageTransaction = true, options = {}) {
|
|
12104
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12105
|
+
if (manageTransaction) db.exec("BEGIN");
|
|
12106
|
+
try {
|
|
12107
|
+
const srcComp = db.prepare(
|
|
12108
|
+
`SELECT description, status, component_description_rationale, props_rationale, slots_rationale
|
|
12109
|
+
FROM raw_components WHERE session_id = ? AND component_id = ?`
|
|
12110
|
+
).get(sourceSessionId, componentId);
|
|
12111
|
+
if (srcComp) {
|
|
12112
|
+
db.prepare(
|
|
12113
|
+
`UPDATE raw_components
|
|
12114
|
+
SET description = ?, status = ?, component_description_rationale = ?, props_rationale = ?, slots_rationale = ?, extracted_at = ?
|
|
12115
|
+
WHERE session_id = ? AND component_id = ?`
|
|
12116
|
+
).run(
|
|
12117
|
+
srcComp.description,
|
|
12118
|
+
srcComp.status,
|
|
12119
|
+
srcComp.component_description_rationale,
|
|
12120
|
+
srcComp.props_rationale,
|
|
12121
|
+
srcComp.slots_rationale,
|
|
12122
|
+
now,
|
|
12123
|
+
targetSessionId,
|
|
12124
|
+
componentId
|
|
12125
|
+
);
|
|
12126
|
+
}
|
|
12127
|
+
const srcProps = db.prepare(
|
|
12128
|
+
`SELECT name, cdf_type, cdf_category, cdf_token_kind, required, description, default_value, rationale
|
|
12129
|
+
FROM raw_props WHERE session_id = ? AND component_id = ?`
|
|
12130
|
+
).all(sourceSessionId, componentId);
|
|
12131
|
+
for (const p of srcProps) {
|
|
12132
|
+
db.prepare(
|
|
12133
|
+
`UPDATE raw_props SET cdf_type = ?, cdf_category = ?, cdf_token_kind = ?, required = ?, description = ?, default_value = ?, rationale = ?
|
|
12134
|
+
WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12135
|
+
).run(
|
|
12136
|
+
p.cdf_type,
|
|
12137
|
+
p.cdf_category,
|
|
12138
|
+
p.cdf_token_kind,
|
|
12139
|
+
p.required,
|
|
12140
|
+
p.description,
|
|
12141
|
+
p.default_value,
|
|
12142
|
+
p.rationale,
|
|
12143
|
+
targetSessionId,
|
|
12144
|
+
componentId,
|
|
12145
|
+
p.name
|
|
12146
|
+
);
|
|
12147
|
+
}
|
|
12148
|
+
db.prepare(`DELETE FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`).run(
|
|
12149
|
+
targetSessionId,
|
|
12150
|
+
componentId
|
|
12151
|
+
);
|
|
12152
|
+
const srcAV = db.prepare(
|
|
12153
|
+
`SELECT prop_name, position, value FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`
|
|
12154
|
+
).all(sourceSessionId, componentId);
|
|
12155
|
+
const insertAV = db.prepare(
|
|
12156
|
+
`INSERT INTO raw_prop_allowed_values (session_id, component_id, prop_name, position, value) VALUES (?, ?, ?, ?, ?)`
|
|
12157
|
+
);
|
|
12158
|
+
for (const av of srcAV) {
|
|
12159
|
+
insertAV.run(targetSessionId, componentId, av.prop_name, av.position, av.value);
|
|
12160
|
+
}
|
|
12161
|
+
const srcSlots = db.prepare(`SELECT name, required, description, rationale FROM raw_slots WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
|
|
12162
|
+
for (const s of srcSlots) {
|
|
12163
|
+
db.prepare(
|
|
12164
|
+
`UPDATE raw_slots SET required = ?, description = ?, rationale = ? WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12165
|
+
).run(s.required, s.description, s.rationale, targetSessionId, componentId, s.name);
|
|
12166
|
+
}
|
|
12167
|
+
db.prepare(`DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`).run(
|
|
12168
|
+
targetSessionId,
|
|
12169
|
+
componentId
|
|
12170
|
+
);
|
|
12171
|
+
const srcSAC = db.prepare(
|
|
12172
|
+
`SELECT slot_name, position, allowed_component FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`
|
|
12173
|
+
).all(sourceSessionId, componentId);
|
|
12174
|
+
const insertSAC = db.prepare(
|
|
12175
|
+
`INSERT INTO raw_slot_allowed_components (session_id, component_id, slot_name, allowed_component, position) VALUES (?, ?, ?, ?, ?)`
|
|
12176
|
+
);
|
|
12177
|
+
const allowedSAC = options.allowedComponentNames ? srcSAC.filter((sac) => options.allowedComponentNames.has(sac.allowed_component)) : srcSAC;
|
|
12178
|
+
for (const sac of allowedSAC) {
|
|
12179
|
+
insertSAC.run(targetSessionId, componentId, sac.slot_name, sac.allowed_component, sac.position);
|
|
12180
|
+
}
|
|
12181
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12182
|
+
if (manageTransaction) db.exec("COMMIT");
|
|
12183
|
+
} catch (e) {
|
|
12184
|
+
if (manageTransaction) db.exec("ROLLBACK");
|
|
12185
|
+
throw e;
|
|
12186
|
+
}
|
|
12187
|
+
}
|
|
12188
|
+
function copyComponentsFromCache(db, entries, options = {}) {
|
|
12189
|
+
if (entries.length === 0) return;
|
|
12190
|
+
db.exec("BEGIN");
|
|
12191
|
+
try {
|
|
12192
|
+
for (const entry of entries) {
|
|
12193
|
+
copyComponentFromCache(db, entry.sourceSessionId, entry.targetSessionId, entry.componentId, false, options);
|
|
12194
|
+
}
|
|
12195
|
+
db.exec("COMMIT");
|
|
12196
|
+
} catch (e) {
|
|
12197
|
+
db.exec("ROLLBACK");
|
|
12198
|
+
throw e;
|
|
12199
|
+
}
|
|
12200
|
+
}
|
|
12201
|
+
function copyTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
11754
12202
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11755
12203
|
db.exec("BEGIN");
|
|
11756
12204
|
try {
|
|
@@ -11771,7 +12219,139 @@ function copyTokensBetweenSessions(db, sourceSessionId, targetSessionId) {
|
|
|
11771
12219
|
throw e;
|
|
11772
12220
|
}
|
|
11773
12221
|
}
|
|
11774
|
-
|
|
12222
|
+
function copyMapTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
12223
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12224
|
+
let copiedCount = 0;
|
|
12225
|
+
db.exec("BEGIN");
|
|
12226
|
+
try {
|
|
12227
|
+
const sourceRows = db.prepare(
|
|
12228
|
+
`SELECT rc.name AS component_name, rptp.prop_name, rptp.source, rptp.position, rptp.path
|
|
12229
|
+
FROM raw_prop_token_paths rptp
|
|
12230
|
+
JOIN raw_components rc ON rc.session_id = rptp.session_id AND rc.component_id = rptp.component_id
|
|
12231
|
+
WHERE rptp.session_id = ?
|
|
12232
|
+
ORDER BY rc.name, rptp.prop_name, rptp.position`
|
|
12233
|
+
).all(sourceSessionId);
|
|
12234
|
+
const targetComponents = db.prepare(`SELECT component_id, name FROM raw_components WHERE session_id = ?`).all(targetSessionId);
|
|
12235
|
+
const targetIdByName = new Map(targetComponents.map((c2) => [c2.name, c2.component_id]));
|
|
12236
|
+
const targetProps = new Set(
|
|
12237
|
+
db.prepare(`SELECT component_id, name FROM raw_props WHERE session_id = ?`).all(targetSessionId).map((p) => `${p.component_id}::${p.name}`)
|
|
12238
|
+
);
|
|
12239
|
+
const insertPath = db.prepare(
|
|
12240
|
+
`INSERT INTO raw_prop_token_paths (session_id, component_id, prop_name, source, position, path)
|
|
12241
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
12242
|
+
);
|
|
12243
|
+
const clearedProps = /* @__PURE__ */ new Set();
|
|
12244
|
+
const copiedProps = /* @__PURE__ */ new Set();
|
|
12245
|
+
for (const row of sourceRows) {
|
|
12246
|
+
const targetComponentId = targetIdByName.get(row.component_name);
|
|
12247
|
+
if (!targetComponentId) continue;
|
|
12248
|
+
if (!targetProps.has(`${targetComponentId}::${row.prop_name}`)) continue;
|
|
12249
|
+
const propKey = `${targetComponentId}::${row.prop_name}`;
|
|
12250
|
+
if (!clearedProps.has(propKey)) {
|
|
12251
|
+
clearedProps.add(propKey);
|
|
12252
|
+
db.prepare(`DELETE FROM raw_prop_token_paths WHERE session_id = ? AND component_id = ? AND prop_name = ?`).run(
|
|
12253
|
+
targetSessionId,
|
|
12254
|
+
targetComponentId,
|
|
12255
|
+
row.prop_name
|
|
12256
|
+
);
|
|
12257
|
+
}
|
|
12258
|
+
insertPath.run(targetSessionId, targetComponentId, row.prop_name, row.source, row.position, row.path);
|
|
12259
|
+
copiedProps.add(propKey);
|
|
12260
|
+
}
|
|
12261
|
+
copiedCount = copiedProps.size;
|
|
12262
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12263
|
+
db.exec("COMMIT");
|
|
12264
|
+
} catch (e) {
|
|
12265
|
+
db.exec("ROLLBACK");
|
|
12266
|
+
throw e;
|
|
12267
|
+
}
|
|
12268
|
+
return copiedCount;
|
|
12269
|
+
}
|
|
12270
|
+
async function getCliCacheVersion() {
|
|
12271
|
+
if (_cliCacheVersionCache) return _cliCacheVersionCache;
|
|
12272
|
+
try {
|
|
12273
|
+
const { hashContent: hashContent2 } = await Promise.resolve().then(() => (init_cache_keys(), cache_keys_exports));
|
|
12274
|
+
const { resolveSkillPath: resolveSkillPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
12275
|
+
const skills = ["components", "tokens", "select"];
|
|
12276
|
+
const parts = [];
|
|
12277
|
+
for (const s of skills) {
|
|
12278
|
+
try {
|
|
12279
|
+
const p = resolveSkillPath2(s);
|
|
12280
|
+
parts.push(readFileSync5(p, "utf8"));
|
|
12281
|
+
} catch {
|
|
12282
|
+
parts.push(`<missing:${s}>`);
|
|
12283
|
+
}
|
|
12284
|
+
}
|
|
12285
|
+
_cliCacheVersionCache = hashContent2(parts.join("\n---\n"));
|
|
12286
|
+
return _cliCacheVersionCache;
|
|
12287
|
+
} catch {
|
|
12288
|
+
_cliCacheVersionCache = "fallback";
|
|
12289
|
+
return _cliCacheVersionCache;
|
|
12290
|
+
}
|
|
12291
|
+
}
|
|
12292
|
+
function storeExtractCache(db, filePath, fileHash, cliVersion2, components) {
|
|
12293
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12294
|
+
const componentsJson = JSON.stringify(components);
|
|
12295
|
+
db.prepare(
|
|
12296
|
+
`INSERT INTO extract_cache (file_path, file_hash, cli_version, created_at, updated_at, components_json)
|
|
12297
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
12298
|
+
ON CONFLICT(file_hash, cli_version) DO UPDATE SET
|
|
12299
|
+
file_path = excluded.file_path,
|
|
12300
|
+
updated_at = excluded.updated_at,
|
|
12301
|
+
components_json = excluded.components_json`
|
|
12302
|
+
).run(filePath, fileHash, cliVersion2, now, now, componentsJson);
|
|
12303
|
+
}
|
|
12304
|
+
function lookupExtractCache(db, fileHash, cliVersion2) {
|
|
12305
|
+
const row = db.prepare(
|
|
12306
|
+
`SELECT file_path, file_hash, cli_version, created_at, updated_at, components_json
|
|
12307
|
+
FROM extract_cache
|
|
12308
|
+
WHERE file_hash = ? AND cli_version = ?`
|
|
12309
|
+
).get(fileHash, cliVersion2);
|
|
12310
|
+
if (!row) return null;
|
|
12311
|
+
let components = [];
|
|
12312
|
+
try {
|
|
12313
|
+
components = JSON.parse(row.components_json);
|
|
12314
|
+
} catch {
|
|
12315
|
+
return null;
|
|
12316
|
+
}
|
|
12317
|
+
return {
|
|
12318
|
+
filePath: row.file_path,
|
|
12319
|
+
fileHash: row.file_hash,
|
|
12320
|
+
cliVersion: row.cli_version,
|
|
12321
|
+
createdAt: row.created_at,
|
|
12322
|
+
updatedAt: row.updated_at,
|
|
12323
|
+
components
|
|
12324
|
+
};
|
|
12325
|
+
}
|
|
12326
|
+
function storeSelectCache(db, componentHash, promptHash, cliVersion2, decision, reason) {
|
|
12327
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12328
|
+
db.prepare(
|
|
12329
|
+
`INSERT INTO select_cache (component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at)
|
|
12330
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
12331
|
+
ON CONFLICT(component_hash, prompt_hash, cli_version) DO UPDATE SET
|
|
12332
|
+
decision = excluded.decision,
|
|
12333
|
+
reason = excluded.reason,
|
|
12334
|
+
updated_at = excluded.updated_at`
|
|
12335
|
+
).run(componentHash, promptHash, cliVersion2, decision, reason, now, now);
|
|
12336
|
+
}
|
|
12337
|
+
function lookupSelectCache(db, componentHash, promptHash, cliVersion2) {
|
|
12338
|
+
const row = db.prepare(
|
|
12339
|
+
`SELECT component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at
|
|
12340
|
+
FROM select_cache
|
|
12341
|
+
WHERE component_hash = ? AND prompt_hash = ? AND cli_version = ?`
|
|
12342
|
+
).get(componentHash, promptHash, cliVersion2);
|
|
12343
|
+
if (!row) return null;
|
|
12344
|
+
return {
|
|
12345
|
+
componentHash: row.component_hash,
|
|
12346
|
+
promptHash: row.prompt_hash,
|
|
12347
|
+
cliVersion: row.cli_version,
|
|
12348
|
+
decision: row.decision,
|
|
12349
|
+
reason: row.reason,
|
|
12350
|
+
createdAt: row.created_at,
|
|
12351
|
+
updatedAt: row.updated_at
|
|
12352
|
+
};
|
|
12353
|
+
}
|
|
12354
|
+
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;
|
|
11775
12355
|
var init_db = __esm({
|
|
11776
12356
|
"packages/experience-design-system-cli-legacy/src/session/db.ts"() {
|
|
11777
12357
|
"use strict";
|
|
@@ -11785,6 +12365,8 @@ var init_db = __esm({
|
|
|
11785
12365
|
init_write2();
|
|
11786
12366
|
init_session_resolver();
|
|
11787
12367
|
init_read3();
|
|
12368
|
+
init_hash_component_shape();
|
|
12369
|
+
init_hash_token_content();
|
|
11788
12370
|
init_read3();
|
|
11789
12371
|
init_store_dtcg_tokens();
|
|
11790
12372
|
init_apply_tool_calls();
|
|
@@ -11908,6 +12490,17 @@ CREATE TABLE IF NOT EXISTS raw_tokens (
|
|
|
11908
12490
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
11909
12491
|
);
|
|
11910
12492
|
|
|
12493
|
+
CREATE TABLE IF NOT EXISTS generation_cache (
|
|
12494
|
+
input_hash TEXT NOT NULL,
|
|
12495
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
12496
|
+
entity_id TEXT NOT NULL,
|
|
12497
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
12498
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
12499
|
+
created_at TEXT NOT NULL,
|
|
12500
|
+
updated_at TEXT NOT NULL,
|
|
12501
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
12502
|
+
);
|
|
12503
|
+
|
|
11911
12504
|
CREATE TABLE IF NOT EXISTS scanned_files (
|
|
11912
12505
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
11913
12506
|
path TEXT NOT NULL,
|
|
@@ -11953,9 +12546,10 @@ CREATE INDEX IF NOT EXISTS idx_raw_props_session ON raw_props(session_id,
|
|
|
11953
12546
|
CREATE INDEX IF NOT EXISTS idx_raw_slots_session ON raw_slots(session_id, component_id);
|
|
11954
12547
|
CREATE INDEX IF NOT EXISTS idx_raw_tokens_session ON raw_tokens(session_id);
|
|
11955
12548
|
CREATE INDEX IF NOT EXISTS idx_raw_token_groups_session ON raw_token_groups(session_id);
|
|
12549
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
12550
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
11956
12551
|
CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session_id);
|
|
11957
12552
|
`;
|
|
11958
|
-
REMOVED_CACHE_TABLES = ["generation_cache", "extract_cache", "composition_cache", "select_cache"];
|
|
11959
12553
|
MAX_COMPONENT_SOURCE_CHARS = 8e3;
|
|
11960
12554
|
MAX_SIBLING_FILES = 5;
|
|
11961
12555
|
MAX_SIBLING_SNIPPET_CHARS = 1200;
|
|
@@ -11972,15 +12566,16 @@ CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session
|
|
|
11972
12566
|
[".cjs", [".cts", ".cjs"]]
|
|
11973
12567
|
];
|
|
11974
12568
|
IDENTIFIER_PATTERN = /[A-Za-z_$][A-Za-z0-9_$]*/g;
|
|
12569
|
+
_cliCacheVersionCache = null;
|
|
11975
12570
|
}
|
|
11976
12571
|
});
|
|
11977
12572
|
|
|
11978
12573
|
// packages/experience-design-system-cli-legacy/src/helpers/read-existing-contentful-entities-from-session.ts
|
|
11979
|
-
import { readFile as
|
|
12574
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
11980
12575
|
async function readExistingContentfulEntitiesFromSession(path) {
|
|
11981
12576
|
if (!path) return void 0;
|
|
11982
12577
|
try {
|
|
11983
|
-
const raw = await
|
|
12578
|
+
const raw = await readFile9(path, "utf8");
|
|
11984
12579
|
const parsed = JSON.parse(raw);
|
|
11985
12580
|
if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens)) return void 0;
|
|
11986
12581
|
return parsed;
|
|
@@ -12104,21 +12699,21 @@ var init_resolve_session_id = __esm({
|
|
|
12104
12699
|
});
|
|
12105
12700
|
|
|
12106
12701
|
// packages/experience-design-system-cli-legacy/src/analyze/select/persistence.ts
|
|
12107
|
-
import { access, appendFile, mkdir as mkdir2, readFile as
|
|
12702
|
+
import { access, appendFile, mkdir as mkdir2, readFile as readFile10, writeFile as writeFile2 } from "node:fs/promises";
|
|
12108
12703
|
import { homedir as homedir4 } from "node:os";
|
|
12109
|
-
import { resolve as
|
|
12704
|
+
import { resolve as resolve10 } from "node:path";
|
|
12110
12705
|
function getRefineArtifactsRoot() {
|
|
12111
12706
|
if (process.env.EDS_REVIEW_ARTIFACTS_DIR) {
|
|
12112
|
-
return
|
|
12707
|
+
return resolve10(process.env.EDS_REVIEW_ARTIFACTS_DIR);
|
|
12113
12708
|
}
|
|
12114
|
-
return
|
|
12709
|
+
return resolve10(homedir4(), ".contentful", "experience-design-system-cli", "reviews");
|
|
12115
12710
|
}
|
|
12116
12711
|
async function getRefineSessionPaths(sessionId2, artifactsRoot) {
|
|
12117
|
-
const sessionDir =
|
|
12712
|
+
const sessionDir = resolve10(artifactsRoot, sessionId2);
|
|
12118
12713
|
return {
|
|
12119
12714
|
sessionDir,
|
|
12120
|
-
eventsPath:
|
|
12121
|
-
statePath:
|
|
12715
|
+
eventsPath: resolve10(sessionDir, "events.jsonl"),
|
|
12716
|
+
statePath: resolve10(sessionDir, "current-review-state.json")
|
|
12122
12717
|
};
|
|
12123
12718
|
}
|
|
12124
12719
|
async function saveReviewState(statePath, session) {
|
|
@@ -12129,7 +12724,7 @@ async function ensureRefineSession(sessionId2, artifactsRoot, initialSnapshot) {
|
|
|
12129
12724
|
await mkdir2(paths.sessionDir, { recursive: true });
|
|
12130
12725
|
try {
|
|
12131
12726
|
await access(paths.statePath);
|
|
12132
|
-
const savedState = await
|
|
12727
|
+
const savedState = await readFile10(paths.statePath, "utf8");
|
|
12133
12728
|
return JSON.parse(savedState);
|
|
12134
12729
|
} catch {
|
|
12135
12730
|
await writeFile2(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
|
|
@@ -12614,8 +13209,8 @@ var init_path_exists = __esm({
|
|
|
12614
13209
|
});
|
|
12615
13210
|
|
|
12616
13211
|
// packages/experience-design-system-cli-legacy/src/lib/prompt-overrides.ts
|
|
12617
|
-
import { readFile as
|
|
12618
|
-
import { resolve as
|
|
13212
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
13213
|
+
import { resolve as resolve11 } from "node:path";
|
|
12619
13214
|
function looksLikePath(value) {
|
|
12620
13215
|
if (value.includes("/") || value.includes("\\")) return true;
|
|
12621
13216
|
if (value.startsWith("~")) return true;
|
|
@@ -12647,9 +13242,9 @@ function parsePromptOverrides(inputs) {
|
|
|
12647
13242
|
}
|
|
12648
13243
|
async function resolvePromptOverride(override) {
|
|
12649
13244
|
if (override.kind === "text") return override.value;
|
|
12650
|
-
const abs =
|
|
13245
|
+
const abs = resolve11(override.value);
|
|
12651
13246
|
try {
|
|
12652
|
-
return await
|
|
13247
|
+
return await readFile11(abs, "utf8");
|
|
12653
13248
|
} catch {
|
|
12654
13249
|
throw new Error(`--prompt: could not read prompt file: ${abs}`);
|
|
12655
13250
|
}
|
|
@@ -12664,21 +13259,21 @@ var init_prompt_overrides = __esm({
|
|
|
12664
13259
|
|
|
12665
13260
|
// packages/experience-design-system-cli-legacy/src/generate/command.ts
|
|
12666
13261
|
import { createElement } from "react";
|
|
12667
|
-
import { readFile as
|
|
12668
|
-
import { join as join14, resolve as
|
|
13262
|
+
import { readFile as readFile12, readdir, stat } from "node:fs/promises";
|
|
13263
|
+
import { join as join14, resolve as resolve12 } from "node:path";
|
|
12669
13264
|
async function assertFileExists(flag, p) {
|
|
12670
13265
|
if (!await pathExists(p)) die(`Error: file not found: ${p} (from ${flag})`);
|
|
12671
13266
|
}
|
|
12672
13267
|
async function readFileInline(path) {
|
|
12673
13268
|
if (!path) return void 0;
|
|
12674
|
-
const resolved =
|
|
13269
|
+
const resolved = resolve12(path);
|
|
12675
13270
|
let s;
|
|
12676
13271
|
try {
|
|
12677
13272
|
s = await stat(resolved);
|
|
12678
13273
|
} catch {
|
|
12679
13274
|
return void 0;
|
|
12680
13275
|
}
|
|
12681
|
-
if (!s.isDirectory()) return
|
|
13276
|
+
if (!s.isDirectory()) return readFile12(resolved, "utf8");
|
|
12682
13277
|
const files = [];
|
|
12683
13278
|
async function walk(dir) {
|
|
12684
13279
|
let entries;
|
|
@@ -12704,7 +13299,7 @@ async function readFileInline(path) {
|
|
|
12704
13299
|
}
|
|
12705
13300
|
await walk(resolved);
|
|
12706
13301
|
if (files.length === 0) return void 0;
|
|
12707
|
-
const parts = await Promise.all(files.map((f) =>
|
|
13302
|
+
const parts = await Promise.all(files.map((f) => readFile12(f, "utf8").catch(() => "")));
|
|
12708
13303
|
return parts.filter(Boolean).join("\n\n");
|
|
12709
13304
|
}
|
|
12710
13305
|
function printFallbackInstructions(options) {
|
|
@@ -12726,6 +13321,23 @@ function printFallbackInstructions(options) {
|
|
|
12726
13321
|
lines.push(` Re-run the generate command with the agent available, or use --dry-run to inspect the prompt.`);
|
|
12727
13322
|
process.stderr.write(lines.join("\n") + "\n");
|
|
12728
13323
|
}
|
|
13324
|
+
function createCachedComponentResult(componentName, warnings = []) {
|
|
13325
|
+
return {
|
|
13326
|
+
componentName,
|
|
13327
|
+
classified: 0,
|
|
13328
|
+
excluded: 0,
|
|
13329
|
+
slots: 0,
|
|
13330
|
+
warnings,
|
|
13331
|
+
failed: false,
|
|
13332
|
+
cached: true,
|
|
13333
|
+
renamedSlotsCount: 0
|
|
13334
|
+
};
|
|
13335
|
+
}
|
|
13336
|
+
function writeCachedComponentStatus(position, componentName, pinned) {
|
|
13337
|
+
const status = pinned ? c.cyan("pinned (human-edited)") : c.green("cached");
|
|
13338
|
+
process.stderr.write(` ${position} ${c.bold(componentName)} ${status}
|
|
13339
|
+
`);
|
|
13340
|
+
}
|
|
12729
13341
|
async function showGenerateView(result) {
|
|
12730
13342
|
if (process.stdout.isTTY) {
|
|
12731
13343
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -12746,6 +13358,29 @@ session=${result.sessionId}
|
|
|
12746
13358
|
);
|
|
12747
13359
|
await exitWithAnalytics(0);
|
|
12748
13360
|
}
|
|
13361
|
+
function normalizeComponentForCache(component) {
|
|
13362
|
+
const slots = component.slots.map((slot, index, allSlots) => ({
|
|
13363
|
+
...slot,
|
|
13364
|
+
name: slot.name.trim() || (allSlots.length === 1 ? "children" : `slot_${index}`)
|
|
13365
|
+
}));
|
|
13366
|
+
return { ...component, slots };
|
|
13367
|
+
}
|
|
13368
|
+
function lookupComponentCache(db, component, promptHash) {
|
|
13369
|
+
const normalized = normalizeComponentForCache(component);
|
|
13370
|
+
const inputHash = hashComponentShape(normalized);
|
|
13371
|
+
const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
|
|
13372
|
+
if (cached) return cached;
|
|
13373
|
+
const legacyInputHash = hashComponentShape(component);
|
|
13374
|
+
return legacyInputHash === inputHash ? null : lookupCache(db, legacyInputHash, "component", component.component_id, promptHash);
|
|
13375
|
+
}
|
|
13376
|
+
function resolveComponentCache(db, component, promptHash, allowedComponentNames2) {
|
|
13377
|
+
const cached = lookupComponentCache(db, component, promptHash);
|
|
13378
|
+
if (cached && findUnknownSlotAllowedComponents(db, cached.sourceSessionId, allowedComponentNames2, component.component_id).length === 0) {
|
|
13379
|
+
return { entry: cached, humanEdited: cached.humanEdited };
|
|
13380
|
+
}
|
|
13381
|
+
const pinned = lookupCacheByEntity(db, "component", component.component_id);
|
|
13382
|
+
return pinned?.humanEdited && findUnknownSlotAllowedComponents(db, pinned.sourceSessionId, allowedComponentNames2, component.component_id).length === 0 ? { entry: pinned, humanEdited: true } : null;
|
|
13383
|
+
}
|
|
12749
13384
|
async function runOneComponent(options, component, index, total) {
|
|
12750
13385
|
const {
|
|
12751
13386
|
agent,
|
|
@@ -12755,10 +13390,13 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12755
13390
|
tokensInline,
|
|
12756
13391
|
tokenMapInline,
|
|
12757
13392
|
verbose,
|
|
13393
|
+
noCache,
|
|
12758
13394
|
skillPathOverride,
|
|
12759
13395
|
skillContentOverride,
|
|
13396
|
+
promptHash,
|
|
12760
13397
|
existingContentfulEntities,
|
|
12761
13398
|
existingTokensInline,
|
|
13399
|
+
precomputedCachedNames,
|
|
12762
13400
|
allowedComponentNames: allowedComponentNames2
|
|
12763
13401
|
} = options;
|
|
12764
13402
|
const pos = c.dim(`[${index + 1}/${total}]`);
|
|
@@ -12783,6 +13421,40 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12783
13421
|
allowedComponents: slot.allowedComponents.filter((name) => allowedComponentNames2.has(name))
|
|
12784
13422
|
};
|
|
12785
13423
|
});
|
|
13424
|
+
const cacheComponent = normalizeComponentForCache(component);
|
|
13425
|
+
if (!noCache && precomputedCachedNames.has(component.name)) {
|
|
13426
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13427
|
+
return createCachedComponentResult(component.name);
|
|
13428
|
+
}
|
|
13429
|
+
if (!noCache) {
|
|
13430
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13431
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13432
|
+
if (resolution && !resolution.humanEdited) {
|
|
13433
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13434
|
+
allowedComponentNames: allowedComponentNames2
|
|
13435
|
+
});
|
|
13436
|
+
storeCache(
|
|
13437
|
+
db,
|
|
13438
|
+
inputHash,
|
|
13439
|
+
"component",
|
|
13440
|
+
component.component_id,
|
|
13441
|
+
resolution.entry.sourceSessionId,
|
|
13442
|
+
resolution.entry.humanEdited,
|
|
13443
|
+
promptHash
|
|
13444
|
+
);
|
|
13445
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13446
|
+
return createCachedComponentResult(component.name);
|
|
13447
|
+
}
|
|
13448
|
+
if (resolution?.humanEdited) {
|
|
13449
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13450
|
+
allowedComponentNames: allowedComponentNames2
|
|
13451
|
+
});
|
|
13452
|
+
writeCachedComponentStatus(pos, component.name, true);
|
|
13453
|
+
return createCachedComponentResult(`${component.name}`, [
|
|
13454
|
+
`${component.name}: source changed but human edits preserved`
|
|
13455
|
+
]);
|
|
13456
|
+
}
|
|
13457
|
+
}
|
|
12786
13458
|
const componentBuckets = bucketComponentProps(component);
|
|
12787
13459
|
getDebugLogger().event("analyze", "prop-buckets.generate", { ...componentBuckets });
|
|
12788
13460
|
const rawComponentsInline = JSON.stringify(
|
|
@@ -12857,6 +13529,10 @@ ${outputBuf}`);
|
|
|
12857
13529
|
const applied = applyToolCalls(db, sessionId2, component.component_id, component.name, calls, warnings, {
|
|
12858
13530
|
allowedComponentNames: allowedComponentNames2
|
|
12859
13531
|
});
|
|
13532
|
+
if (!noCache) {
|
|
13533
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13534
|
+
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
13535
|
+
}
|
|
12860
13536
|
return {
|
|
12861
13537
|
componentName: component.name,
|
|
12862
13538
|
classified: applied.classified,
|
|
@@ -12908,7 +13584,7 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12908
13584
|
try {
|
|
12909
13585
|
const artifactsRoot = getRefineArtifactsRoot();
|
|
12910
13586
|
const paths = await getRefineSessionPaths(sessionId2, artifactsRoot);
|
|
12911
|
-
const raw = await
|
|
13587
|
+
const raw = await readFile12(paths.statePath, "utf8");
|
|
12912
13588
|
const snapshot = JSON.parse(raw);
|
|
12913
13589
|
const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
|
|
12914
13590
|
if (accepted.length === 0) return null;
|
|
@@ -12917,6 +13593,15 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12917
13593
|
return null;
|
|
12918
13594
|
}
|
|
12919
13595
|
}
|
|
13596
|
+
function parsePrecomputedCachedNames(value) {
|
|
13597
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
13598
|
+
try {
|
|
13599
|
+
const parsed = JSON.parse(value);
|
|
13600
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((name) => typeof name === "string") : []);
|
|
13601
|
+
} catch {
|
|
13602
|
+
return /* @__PURE__ */ new Set();
|
|
13603
|
+
}
|
|
13604
|
+
}
|
|
12920
13605
|
async function runGenerateSkill(skill, opts, verbose = false) {
|
|
12921
13606
|
const savedCreds = await readExperiencesCredentials();
|
|
12922
13607
|
const agentName = opts.agent ?? savedCreds.agent;
|
|
@@ -12945,8 +13630,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12945
13630
|
}
|
|
12946
13631
|
const generatePromptPath = generatePrompt === void 0 ? configuredGeneratePromptPath : void 0;
|
|
12947
13632
|
if (generatePromptPath) {
|
|
12948
|
-
if (!await pathExists(
|
|
12949
|
-
die(`Error: custom prompt path not found: ${
|
|
13633
|
+
if (!await pathExists(resolve12(generatePromptPath))) {
|
|
13634
|
+
die(`Error: custom prompt path not found: ${resolve12(generatePromptPath)}`);
|
|
12950
13635
|
}
|
|
12951
13636
|
if (!generatePromptPath.toLowerCase().endsWith(".md")) {
|
|
12952
13637
|
process.stderr.write(
|
|
@@ -12954,7 +13639,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12954
13639
|
`
|
|
12955
13640
|
);
|
|
12956
13641
|
}
|
|
12957
|
-
process.stderr.write(formatCustomPromptBanner("components",
|
|
13642
|
+
process.stderr.write(formatCustomPromptBanner("components", resolve12(generatePromptPath)));
|
|
12958
13643
|
}
|
|
12959
13644
|
if (skill === "tokens" && !opts.rawTokens) {
|
|
12960
13645
|
die("Error: --raw-tokens is required when using generate tokens");
|
|
@@ -12970,7 +13655,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12970
13655
|
let existingContentfulEntities;
|
|
12971
13656
|
let existingTokensInline;
|
|
12972
13657
|
if (opts.existingEntitiesPath) {
|
|
12973
|
-
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
13658
|
+
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(resolve12(opts.existingEntitiesPath));
|
|
12974
13659
|
if (existingContentfulEntities) {
|
|
12975
13660
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
12976
13661
|
} else {
|
|
@@ -13071,7 +13756,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13071
13756
|
rawComponentsInline: sampleInline ?? rawTokensInline,
|
|
13072
13757
|
propBucketsInline: sampleBuckets ? JSON.stringify(sampleBuckets) : void 0,
|
|
13073
13758
|
rawTokensInline: skill === "tokens" ? rawTokensInline : void 0,
|
|
13074
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13759
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13075
13760
|
tokensInline,
|
|
13076
13761
|
tokenMapInline,
|
|
13077
13762
|
outDir: process.cwd(),
|
|
@@ -13097,7 +13782,64 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13097
13782
|
if (skill === "components" && allComponents && sessionId2) {
|
|
13098
13783
|
const db = openPipelineDb();
|
|
13099
13784
|
let componentResults;
|
|
13785
|
+
const precomputedCachedNames = parsePrecomputedCachedNames(opts.cachedComponents);
|
|
13100
13786
|
try {
|
|
13787
|
+
const existingContentfulEntitiesHashInputs = [];
|
|
13788
|
+
if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
|
|
13789
|
+
const promptHash = await hashPromptForSkill(
|
|
13790
|
+
"components",
|
|
13791
|
+
agent,
|
|
13792
|
+
model,
|
|
13793
|
+
generatePromptPath,
|
|
13794
|
+
existingContentfulEntitiesHashInputs,
|
|
13795
|
+
generatePrompt
|
|
13796
|
+
);
|
|
13797
|
+
if (opts.cacheStatus) {
|
|
13798
|
+
const cacheEnabled = opts.cache !== false && process.env.EDS_NO_CACHE !== "1";
|
|
13799
|
+
const cachedComponents = cacheEnabled ? allComponents.flatMap((component) => {
|
|
13800
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13801
|
+
return resolution ? [{ component, resolution }] : [];
|
|
13802
|
+
}) : [];
|
|
13803
|
+
if (cacheEnabled && opts.restoreCache) {
|
|
13804
|
+
const restorations = [];
|
|
13805
|
+
const rekeyed = [];
|
|
13806
|
+
const componentStatus = db.prepare(
|
|
13807
|
+
"SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?"
|
|
13808
|
+
);
|
|
13809
|
+
for (const { component, resolution } of cachedComponents) {
|
|
13810
|
+
const current = componentStatus.get(sessionId2, component.component_id);
|
|
13811
|
+
if (current?.status === "generated") continue;
|
|
13812
|
+
renameEmptySlots(db, sessionId2, component.component_id, component.name, component.slots.length);
|
|
13813
|
+
restorations.push({
|
|
13814
|
+
sourceSessionId: resolution.entry.sourceSessionId,
|
|
13815
|
+
targetSessionId: sessionId2,
|
|
13816
|
+
componentId: component.component_id
|
|
13817
|
+
});
|
|
13818
|
+
rekeyed.push({ component, cached: resolution.entry });
|
|
13819
|
+
}
|
|
13820
|
+
copyComponentsFromCache(db, restorations, { allowedComponentNames: allowedComponentNames2 });
|
|
13821
|
+
storeCaches(
|
|
13822
|
+
db,
|
|
13823
|
+
rekeyed.map(({ component, cached }) => ({
|
|
13824
|
+
inputHash: hashComponentShape(normalizeComponentForCache(component)),
|
|
13825
|
+
entityType: "component",
|
|
13826
|
+
entityId: component.component_id,
|
|
13827
|
+
sourceSessionId: cached.sourceSessionId,
|
|
13828
|
+
humanEdited: cached.humanEdited,
|
|
13829
|
+
promptHash
|
|
13830
|
+
}))
|
|
13831
|
+
);
|
|
13832
|
+
}
|
|
13833
|
+
const fullyCached = cacheEnabled && cachedComponents.length === allComponents.length;
|
|
13834
|
+
process.stdout.write(`cache-status=${fullyCached ? "hit" : "miss"}
|
|
13835
|
+
`);
|
|
13836
|
+
process.stdout.write(
|
|
13837
|
+
`cache-components=${JSON.stringify(cachedComponents.map(({ component }) => component.name))}
|
|
13838
|
+
`
|
|
13839
|
+
);
|
|
13840
|
+
await exitWithAnalytics(0);
|
|
13841
|
+
return;
|
|
13842
|
+
}
|
|
13101
13843
|
componentResults = await runAllComponents(
|
|
13102
13844
|
{
|
|
13103
13845
|
agent,
|
|
@@ -13107,10 +13849,13 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13107
13849
|
tokensInline,
|
|
13108
13850
|
tokenMapInline,
|
|
13109
13851
|
verbose,
|
|
13852
|
+
noCache: opts.cache === false || process.env.EDS_NO_CACHE === "1",
|
|
13110
13853
|
skillPathOverride: generatePromptPath,
|
|
13111
13854
|
skillContentOverride: generatePrompt,
|
|
13855
|
+
promptHash,
|
|
13112
13856
|
existingContentfulEntities,
|
|
13113
13857
|
existingTokensInline,
|
|
13858
|
+
precomputedCachedNames,
|
|
13114
13859
|
allowedComponentNames: allowedComponentNames2
|
|
13115
13860
|
},
|
|
13116
13861
|
allComponents
|
|
@@ -13119,7 +13864,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13119
13864
|
db.close();
|
|
13120
13865
|
}
|
|
13121
13866
|
const failed = componentResults.filter((r) => r.failed);
|
|
13122
|
-
const
|
|
13867
|
+
const cachedResults = componentResults.filter((r) => r.cached);
|
|
13868
|
+
const generated = componentResults.filter((r) => !r.failed && !r.cached);
|
|
13123
13869
|
const allWarnings = componentResults.flatMap((r) => r.warnings.map((w) => ` ${r.componentName}: ${w}`));
|
|
13124
13870
|
if (allWarnings.length > 0) {
|
|
13125
13871
|
process.stderr.write(c.yellow("Warnings:") + "\n" + allWarnings.join("\n") + "\n");
|
|
@@ -13135,17 +13881,21 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13135
13881
|
const totalExcluded = generated.reduce((s, r) => s + r.excluded, 0);
|
|
13136
13882
|
const totalRenamedSlots = componentResults.reduce((s, r) => s + r.renamedSlotsCount, 0);
|
|
13137
13883
|
const allOk = failed.length === 0;
|
|
13884
|
+
const cachedNote = cachedResults.length > 0 ? c.dim(` (${cachedResults.length} cached)`) : "";
|
|
13138
13885
|
process.stderr.write(
|
|
13139
|
-
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length}/${componentResults.length} components` + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13886
|
+
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length + cachedResults.length}/${componentResults.length} components` + cachedNote + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13140
13887
|
);
|
|
13141
13888
|
process.stdout.write(`renamed-slots: ${totalRenamedSlots}
|
|
13142
13889
|
`);
|
|
13143
|
-
if (generated.length === 0) {
|
|
13890
|
+
if (generated.length === 0 && cachedResults.length === 0) {
|
|
13144
13891
|
die(
|
|
13145
13892
|
`Error: all ${componentResults.length} component(s) failed to generate \u2014 see the per-component errors above.`
|
|
13146
13893
|
);
|
|
13147
13894
|
}
|
|
13148
13895
|
} else if (skill === "tokens") {
|
|
13896
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
13897
|
+
const tokenInputContent = rawTokensInline ?? "";
|
|
13898
|
+
const tokenInputHash = hashTokenContent(tokenInputContent);
|
|
13149
13899
|
const db = openPipelineDb();
|
|
13150
13900
|
try {
|
|
13151
13901
|
let resolvedSessionId = opts.session;
|
|
@@ -13172,11 +13922,26 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13172
13922
|
}
|
|
13173
13923
|
sessionId2 = resolvedSessionId;
|
|
13174
13924
|
await bindAnalyticsSessionId(resolvedSessionId);
|
|
13925
|
+
const tokenPromptHash = await hashPromptForSkill("tokens", agent, model);
|
|
13926
|
+
if (!noCache) {
|
|
13927
|
+
const tokenCached = lookupCache(db, tokenInputHash, "token_set", "__tokens__", tokenPromptHash);
|
|
13928
|
+
if (tokenCached) {
|
|
13929
|
+
copyTokensFromCache(db, tokenCached.sourceSessionId, resolvedSessionId);
|
|
13930
|
+
sessionId2 = resolvedSessionId;
|
|
13931
|
+
process.stderr.write(
|
|
13932
|
+
`Done: tokens reused from cache ${c.dim(`(source: ${tokenCached.sourceSessionId.slice(0, 12)})`)}
|
|
13933
|
+
`
|
|
13934
|
+
);
|
|
13935
|
+
db.close();
|
|
13936
|
+
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13937
|
+
return;
|
|
13938
|
+
}
|
|
13939
|
+
}
|
|
13175
13940
|
const prompt = await buildPrompt({
|
|
13176
13941
|
skill,
|
|
13177
13942
|
mode: "autonomous",
|
|
13178
13943
|
rawTokensInline,
|
|
13179
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13944
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13180
13945
|
tokensInline,
|
|
13181
13946
|
tokenMapInline,
|
|
13182
13947
|
outDir: process.cwd()
|
|
@@ -13213,6 +13978,9 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13213
13978
|
`);
|
|
13214
13979
|
}
|
|
13215
13980
|
applyTokenToolCalls(db, resolvedSessionId, tokenCalls, []);
|
|
13981
|
+
if (!noCache) {
|
|
13982
|
+
storeCache(db, tokenInputHash, "token_set", "__tokens__", resolvedSessionId, false, tokenPromptHash);
|
|
13983
|
+
}
|
|
13216
13984
|
sessionId2 = resolvedSessionId;
|
|
13217
13985
|
const groupCount = tokenCalls.filter((tc) => tc.tool === "set_group").length;
|
|
13218
13986
|
process.stderr.write(`Done: ${tokenCount} tokens, ${groupCount} groups stored
|
|
@@ -13224,7 +13992,10 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13224
13992
|
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13225
13993
|
}
|
|
13226
13994
|
function addAgentFlags(cmd) {
|
|
13227
|
-
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent")
|
|
13995
|
+
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent").option(
|
|
13996
|
+
"--no-cache",
|
|
13997
|
+
"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."
|
|
13998
|
+
);
|
|
13228
13999
|
}
|
|
13229
14000
|
function registerInternalGenerateCommand(program) {
|
|
13230
14001
|
const generate = program.command("__generate", { hidden: true }).description("Internal import pipeline generation command");
|
|
@@ -13240,6 +14011,12 @@ function registerInternalGenerateCommand(program) {
|
|
|
13240
14011
|
"--existing-entities-path <path>",
|
|
13241
14012
|
"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."
|
|
13242
14013
|
);
|
|
14014
|
+
componentsCmd.option("--cache-status", "Check whether all selected component definitions are cached");
|
|
14015
|
+
componentsCmd.option("--restore-cache", "Restore cached component definitions into the current session");
|
|
14016
|
+
componentsCmd.option(
|
|
14017
|
+
"--cached-components <json>",
|
|
14018
|
+
"Component names already restored by a prior cache-status lookup; skip per-component cache lookup"
|
|
14019
|
+
);
|
|
13243
14020
|
addAgentFlags(componentsCmd).action(async (opts) => {
|
|
13244
14021
|
await runGenerateSkill("components", opts, opts.verbose ?? false);
|
|
13245
14022
|
});
|
|
@@ -13265,6 +14042,7 @@ var init_command = __esm({
|
|
|
13265
14042
|
init_agent_output();
|
|
13266
14043
|
init_GenerateView();
|
|
13267
14044
|
init_db();
|
|
14045
|
+
init_cache_keys();
|
|
13268
14046
|
init_read_existing_contentful_entities_from_session();
|
|
13269
14047
|
init_summarize_existing_contentful_entities();
|
|
13270
14048
|
init_resolve_session_id();
|
|
@@ -13980,7 +14758,7 @@ var init_user_agent = __esm({
|
|
|
13980
14758
|
// packages/experience-design-system-cli-legacy/src/apply/api-client.ts
|
|
13981
14759
|
import { parseCDFComponents } from "@contentful/experience-design-system-types";
|
|
13982
14760
|
function defaultSleep(delayMs) {
|
|
13983
|
-
return new Promise((
|
|
14761
|
+
return new Promise((resolve21) => setTimeout(resolve21, delayMs));
|
|
13984
14762
|
}
|
|
13985
14763
|
function isTransientStatus(status) {
|
|
13986
14764
|
return status >= 500 && status <= 599;
|
|
@@ -14370,7 +15148,7 @@ ${trimmed}`;
|
|
|
14370
15148
|
const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
|
|
14371
15149
|
const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
|
|
14372
15150
|
const jitter = Math.random() * baseDelay * 0.15;
|
|
14373
|
-
await new Promise((
|
|
15151
|
+
await new Promise((resolve21) => setTimeout(resolve21, baseDelay + jitter));
|
|
14374
15152
|
}
|
|
14375
15153
|
}
|
|
14376
15154
|
throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
|
|
@@ -15180,7 +15958,7 @@ var init_terminal_capabilities = __esm({
|
|
|
15180
15958
|
|
|
15181
15959
|
// packages/experience-design-system-cli-legacy/src/apply/command.ts
|
|
15182
15960
|
import { createElement as createElement2 } from "react";
|
|
15183
|
-
import { readFile as
|
|
15961
|
+
import { readFile as readFile13, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
15184
15962
|
import { join as join16 } from "node:path";
|
|
15185
15963
|
import {
|
|
15186
15964
|
validateCDF,
|
|
@@ -15201,7 +15979,7 @@ function dieWithApiError(error) {
|
|
|
15201
15979
|
async function readJsonFile(flag, p) {
|
|
15202
15980
|
let text;
|
|
15203
15981
|
try {
|
|
15204
|
-
text = await
|
|
15982
|
+
text = await readFile13(p, "utf8");
|
|
15205
15983
|
} catch {
|
|
15206
15984
|
return await die2(`Error: file not found: ${p} (from ${flag})`);
|
|
15207
15985
|
}
|
|
@@ -15255,7 +16033,7 @@ async function readTokensFromPath(flag, p) {
|
|
|
15255
16033
|
for (const file of files.sort()) {
|
|
15256
16034
|
let text;
|
|
15257
16035
|
try {
|
|
15258
|
-
text = await
|
|
16036
|
+
text = await readFile13(file, "utf8");
|
|
15259
16037
|
} catch {
|
|
15260
16038
|
continue;
|
|
15261
16039
|
}
|
|
@@ -15624,11 +16402,11 @@ var init_command2 = __esm({
|
|
|
15624
16402
|
});
|
|
15625
16403
|
|
|
15626
16404
|
// packages/experience-design-system-cli-legacy/src/print/validate/validators/read-json-file.ts
|
|
15627
|
-
import { readFile as
|
|
16405
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
15628
16406
|
async function readJsonFile2(filePath) {
|
|
15629
16407
|
let content;
|
|
15630
16408
|
try {
|
|
15631
|
-
content = await
|
|
16409
|
+
content = await readFile14(filePath, "utf-8");
|
|
15632
16410
|
} catch (err) {
|
|
15633
16411
|
return {
|
|
15634
16412
|
ok: false,
|
|
@@ -16039,7 +16817,7 @@ var init_ValidateView = __esm({
|
|
|
16039
16817
|
// packages/experience-design-system-cli-legacy/src/print/command.ts
|
|
16040
16818
|
import { createElement as createElement3 } from "react";
|
|
16041
16819
|
import { access as access3, mkdir as mkdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
16042
|
-
import { basename as basename5, resolve as
|
|
16820
|
+
import { basename as basename5, resolve as resolve13 } from "node:path";
|
|
16043
16821
|
import { CDF_SCHEMA_URL } from "@contentful/experience-design-system-types";
|
|
16044
16822
|
async function die3(message) {
|
|
16045
16823
|
process.stderr.write(`${message}
|
|
@@ -16106,7 +16884,7 @@ function registerPrintCommand(program) {
|
|
|
16106
16884
|
"--allow-empty",
|
|
16107
16885
|
"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."
|
|
16108
16886
|
).action(async (opts) => {
|
|
16109
|
-
const outPath =
|
|
16887
|
+
const outPath = resolve13(opts.out);
|
|
16110
16888
|
await assertOutIsNotDirectory(outPath);
|
|
16111
16889
|
const sessionId2 = await resolveSession(opts.session, "generate components");
|
|
16112
16890
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16154,7 +16932,7 @@ function registerPrintCommand(program) {
|
|
|
16154
16932
|
`
|
|
16155
16933
|
);
|
|
16156
16934
|
}
|
|
16157
|
-
await mkdir3(
|
|
16935
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16158
16936
|
await writeFile3(outPath, `${JSON.stringify(cdfObj, null, 2)}
|
|
16159
16937
|
`);
|
|
16160
16938
|
process.stdout.write(
|
|
@@ -16163,7 +16941,7 @@ function registerPrintCommand(program) {
|
|
|
16163
16941
|
);
|
|
16164
16942
|
});
|
|
16165
16943
|
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) => {
|
|
16166
|
-
const outPath =
|
|
16944
|
+
const outPath = resolve13(opts.out);
|
|
16167
16945
|
await assertOutIsNotDirectory(outPath);
|
|
16168
16946
|
const sessionId2 = await resolveSession(opts.session, "generate tokens");
|
|
16169
16947
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16178,7 +16956,7 @@ function registerPrintCommand(program) {
|
|
|
16178
16956
|
await die3(`Error: no generated tokens in session '${sessionId2}'. Run generate tokens first.`);
|
|
16179
16957
|
}
|
|
16180
16958
|
const tree = rebuildDTCGTree(result.groups, result.tokens);
|
|
16181
|
-
await mkdir3(
|
|
16959
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16182
16960
|
await writeFile3(outPath, `${JSON.stringify(tree, null, 2)}
|
|
16183
16961
|
`);
|
|
16184
16962
|
process.stdout.write(
|
|
@@ -16327,7 +17105,7 @@ function MapTokensView({ result, onExit }) {
|
|
|
16327
17105
|
const timer = setTimeout(onExit, 100);
|
|
16328
17106
|
return () => clearTimeout(timer);
|
|
16329
17107
|
}, [onExit]);
|
|
16330
|
-
const summary = `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
17108
|
+
const summary = result.cached ? "reused from cache" : `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
16331
17109
|
return /* @__PURE__ */ jsx8(
|
|
16332
17110
|
CommandCompletionView,
|
|
16333
17111
|
{
|
|
@@ -16461,8 +17239,8 @@ var init_resolve_defaults = __esm({
|
|
|
16461
17239
|
|
|
16462
17240
|
// packages/experience-design-system-cli-legacy/src/map-tokens/command.ts
|
|
16463
17241
|
import { createElement as createElement4 } from "react";
|
|
16464
|
-
import { readFile as
|
|
16465
|
-
import { resolve as
|
|
17242
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
17243
|
+
import { resolve as resolve14 } from "node:path";
|
|
16466
17244
|
async function renderResult(result) {
|
|
16467
17245
|
if (process.stdout.isTTY) {
|
|
16468
17246
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -16470,13 +17248,12 @@ async function renderResult(result) {
|
|
|
16470
17248
|
);
|
|
16471
17249
|
await waitUntilExit();
|
|
16472
17250
|
} else {
|
|
16473
|
-
|
|
16474
|
-
|
|
17251
|
+
const summary = result.cached ? "cached" : `${result.applied} mapping(s) applied`;
|
|
17252
|
+
process.stdout.write(`map tokens complete
|
|
16475
17253
|
agent: ${result.agent}
|
|
16476
17254
|
session=${result.sessionId}
|
|
16477
|
-
${
|
|
16478
|
-
`
|
|
16479
|
-
);
|
|
17255
|
+
${summary}
|
|
17256
|
+
`);
|
|
16480
17257
|
await exitWithAnalytics(0);
|
|
16481
17258
|
}
|
|
16482
17259
|
}
|
|
@@ -16498,7 +17275,7 @@ async function runMapTokens(opts) {
|
|
|
16498
17275
|
let mapPromptPath;
|
|
16499
17276
|
if (mapPromptOverride?.kind === "text") mapPromptText = mapPromptOverride.value;
|
|
16500
17277
|
if (mapPromptOverride?.kind === "path") {
|
|
16501
|
-
mapPromptPath =
|
|
17278
|
+
mapPromptPath = resolve14(mapPromptOverride.value);
|
|
16502
17279
|
try {
|
|
16503
17280
|
await resolvePromptOverride(mapPromptOverride);
|
|
16504
17281
|
} catch (error) {
|
|
@@ -16518,7 +17295,7 @@ async function runMapTokens(opts) {
|
|
|
16518
17295
|
const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
|
|
16519
17296
|
const tokenMapDiagnostics = [];
|
|
16520
17297
|
if (opts.tokenMap) {
|
|
16521
|
-
const fileMappings = JSON.parse(await
|
|
17298
|
+
const fileMappings = JSON.parse(await readFile15(opts.tokenMap, "utf8"));
|
|
16522
17299
|
const validMappings = {};
|
|
16523
17300
|
for (const [rawName, path] of Object.entries(fileMappings)) {
|
|
16524
17301
|
if (knownTokenPaths.has(path)) {
|
|
@@ -16596,7 +17373,7 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16596
17373
|
let existingTokensInline;
|
|
16597
17374
|
if (opts.existingEntitiesPath) {
|
|
16598
17375
|
const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
16599
|
-
|
|
17376
|
+
resolve14(opts.existingEntitiesPath)
|
|
16600
17377
|
);
|
|
16601
17378
|
if (existingContentfulEntities) {
|
|
16602
17379
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
@@ -16631,10 +17408,30 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16631
17408
|
skipAgent: "true"
|
|
16632
17409
|
});
|
|
16633
17410
|
updateStep(db, stepId2, "complete", { applied: "0", skipAgent: "true" });
|
|
16634
|
-
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0 });
|
|
17411
|
+
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0, cached: false });
|
|
16635
17412
|
return;
|
|
16636
17413
|
}
|
|
16637
17414
|
const agent = configuredAgent;
|
|
17415
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
17416
|
+
const promptHash = await hashPromptForSkill(
|
|
17417
|
+
"map-tokens",
|
|
17418
|
+
agent,
|
|
17419
|
+
model,
|
|
17420
|
+
void 0,
|
|
17421
|
+
existingTokensInline ? [hashContent(existingTokensInline)] : [],
|
|
17422
|
+
mapPromptText
|
|
17423
|
+
);
|
|
17424
|
+
const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
|
|
17425
|
+
if (!noCache) {
|
|
17426
|
+
const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
|
|
17427
|
+
if (cached) {
|
|
17428
|
+
const appliedFromCache = copyMapTokensFromCache(db, cached.sourceSessionId, sessionId2);
|
|
17429
|
+
const stepId2 = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
|
|
17430
|
+
updateStep(db, stepId2, "complete", { cached: "true", applied: String(appliedFromCache) });
|
|
17431
|
+
await renderResult({ agent, sessionId: sessionId2, applied: appliedFromCache, cached: true });
|
|
17432
|
+
return;
|
|
17433
|
+
}
|
|
17434
|
+
}
|
|
16638
17435
|
const binary = resolveAgentBinary(agent);
|
|
16639
17436
|
if (!await assertBinaryInPath(binary)) {
|
|
16640
17437
|
die(
|
|
@@ -16654,20 +17451,23 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
16654
17451
|
}
|
|
16655
17452
|
const { calls, warnings: parseWarnings } = parseMapTokenPropToolCallLines(result.stdout);
|
|
16656
17453
|
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, calls, parseWarnings);
|
|
17454
|
+
if (!noCache) {
|
|
17455
|
+
storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId2, false, promptHash);
|
|
17456
|
+
}
|
|
16657
17457
|
updateStep(db, stepId, "complete", { applied: String(applied), warnings: String(warnings.length) });
|
|
16658
17458
|
if (warnings.length > 0) {
|
|
16659
17459
|
process.stderr.write(`Warnings:
|
|
16660
17460
|
${warnings.map((w) => ` ${w}`).join("\n")}
|
|
16661
17461
|
`);
|
|
16662
17462
|
}
|
|
16663
|
-
await renderResult({ agent, sessionId: sessionId2, applied });
|
|
17463
|
+
await renderResult({ agent, sessionId: sessionId2, applied, cached: false });
|
|
16664
17464
|
} finally {
|
|
16665
17465
|
db.close();
|
|
16666
17466
|
}
|
|
16667
17467
|
}
|
|
16668
17468
|
function registerMapTokensCommand(program) {
|
|
16669
17469
|
const map = program.command("map", { hidden: true }).description("Suggest token restrictions for generated design-token props");
|
|
16670
|
-
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(
|
|
17470
|
+
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(
|
|
16671
17471
|
"--prompt <stage=value>",
|
|
16672
17472
|
"Override a stage prompt (repeatable). Used here for the map-tokens stage.",
|
|
16673
17473
|
(v, acc) => [...acc, v],
|
|
@@ -16687,6 +17487,7 @@ var init_command4 = __esm({
|
|
|
16687
17487
|
init_render_with_goodbye();
|
|
16688
17488
|
init_src();
|
|
16689
17489
|
init_db();
|
|
17490
|
+
init_cache_keys();
|
|
16690
17491
|
init_read_existing_contentful_entities_from_session();
|
|
16691
17492
|
init_summarize_existing_contentful_entities();
|
|
16692
17493
|
init_command3();
|
|
@@ -16703,7 +17504,7 @@ var init_command4 = __esm({
|
|
|
16703
17504
|
});
|
|
16704
17505
|
|
|
16705
17506
|
// packages/experience-design-system-cli-legacy/src/import/path-utils.ts
|
|
16706
|
-
import { resolve as
|
|
17507
|
+
import { resolve as resolve15 } from "node:path";
|
|
16707
17508
|
import { homedir as homedir5 } from "node:os";
|
|
16708
17509
|
function expandTilde(input) {
|
|
16709
17510
|
if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
|
|
@@ -16717,7 +17518,7 @@ function normalizePath(input) {
|
|
|
16717
17518
|
p = p.slice(1, -1);
|
|
16718
17519
|
}
|
|
16719
17520
|
p = expandTilde(p);
|
|
16720
|
-
return
|
|
17521
|
+
return resolve15(p);
|
|
16721
17522
|
}
|
|
16722
17523
|
var init_path_utils = __esm({
|
|
16723
17524
|
"packages/experience-design-system-cli-legacy/src/import/path-utils.ts"() {
|
|
@@ -16942,7 +17743,7 @@ var init_save_path_resolver = __esm({
|
|
|
16942
17743
|
});
|
|
16943
17744
|
|
|
16944
17745
|
// packages/experience-design-system-cli-legacy/src/runs/store.ts
|
|
16945
|
-
import { readFile as
|
|
17746
|
+
import { readFile as readFile16, writeFile as writeFile4, mkdir as mkdir4, rename } from "node:fs/promises";
|
|
16946
17747
|
import { join as join20 } from "node:path";
|
|
16947
17748
|
import { homedir as homedir6 } from "node:os";
|
|
16948
17749
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -16982,7 +17783,7 @@ function migrateRecord(rec) {
|
|
|
16982
17783
|
}
|
|
16983
17784
|
async function readFileMaybe() {
|
|
16984
17785
|
try {
|
|
16985
|
-
const raw = await
|
|
17786
|
+
const raw = await readFile16(RUNS_PATH, "utf8");
|
|
16986
17787
|
const parsed = JSON.parse(raw);
|
|
16987
17788
|
if (!READABLE_VERSIONS.has(parsed.version)) {
|
|
16988
17789
|
throw new Error(
|
|
@@ -17046,15 +17847,15 @@ var init_store = __esm({
|
|
|
17046
17847
|
});
|
|
17047
17848
|
|
|
17048
17849
|
// packages/experience-design-system-cli-legacy/src/runs/fingerprint.ts
|
|
17049
|
-
import { createHash as
|
|
17050
|
-
import { readFile as
|
|
17051
|
-
import { resolve as
|
|
17850
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
17851
|
+
import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
|
|
17852
|
+
import { resolve as resolve16 } from "node:path";
|
|
17052
17853
|
function rowField(row, key) {
|
|
17053
17854
|
const v = row[key];
|
|
17054
17855
|
return typeof v === "string" ? v : null;
|
|
17055
17856
|
}
|
|
17056
17857
|
function sha256Hex(buf) {
|
|
17057
|
-
return
|
|
17858
|
+
return createHash6("sha256").update(buf).digest("hex");
|
|
17058
17859
|
}
|
|
17059
17860
|
async function buildSourceFingerprint(opts) {
|
|
17060
17861
|
const rows = opts.db.prepare("SELECT name, source_path FROM raw_components WHERE session_id = ?").all(opts.extractSessionId);
|
|
@@ -17064,7 +17865,7 @@ async function buildSourceFingerprint(opts) {
|
|
|
17064
17865
|
const sourcePath = rowField(row, "source_path");
|
|
17065
17866
|
const name = rowField(row, "name");
|
|
17066
17867
|
if (!sourcePath) continue;
|
|
17067
|
-
const abs =
|
|
17868
|
+
const abs = resolve16(sourcePath);
|
|
17068
17869
|
if (seen.has(abs)) continue;
|
|
17069
17870
|
seen.add(abs);
|
|
17070
17871
|
try {
|
|
@@ -17079,10 +17880,10 @@ async function buildSourceFingerprint(opts) {
|
|
|
17079
17880
|
let rawTokensMtime = null;
|
|
17080
17881
|
let rawTokensContentHash = null;
|
|
17081
17882
|
if (opts.rawTokensPath) {
|
|
17082
|
-
const abs =
|
|
17883
|
+
const abs = resolve16(opts.rawTokensPath);
|
|
17083
17884
|
rawTokensPath = abs;
|
|
17084
17885
|
try {
|
|
17085
|
-
const [st, buf] = await Promise.all([stat4(abs),
|
|
17886
|
+
const [st, buf] = await Promise.all([stat4(abs), readFile17(abs)]);
|
|
17086
17887
|
rawTokensMtime = st.mtime.toISOString();
|
|
17087
17888
|
rawTokensContentHash = sha256Hex(buf);
|
|
17088
17889
|
} catch {
|
|
@@ -18837,11 +19638,11 @@ var init_slot_graph = __esm({
|
|
|
18837
19638
|
});
|
|
18838
19639
|
|
|
18839
19640
|
// packages/experience-design-system-cli-legacy/src/analyze/select/parser.ts
|
|
18840
|
-
import { createHash as
|
|
19641
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
18841
19642
|
import { access as access5 } from "node:fs/promises";
|
|
18842
|
-
import { isAbsolute, relative, resolve as
|
|
19643
|
+
import { isAbsolute, relative, resolve as resolve17 } from "node:path";
|
|
18843
19644
|
function createComponentId(name, resolvedSourcePath) {
|
|
18844
|
-
const sourceHash =
|
|
19645
|
+
const sourceHash = createHash7("sha256").update(`${name}:${resolvedSourcePath}`).digest("hex").slice(0, 12);
|
|
18845
19646
|
return `${name}-${sourceHash}`;
|
|
18846
19647
|
}
|
|
18847
19648
|
async function resolveComponentSourcePath(source, reviewRoot) {
|
|
@@ -18853,7 +19654,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18853
19654
|
throw new Error(`Unable to access component source at ${source}`);
|
|
18854
19655
|
}
|
|
18855
19656
|
}
|
|
18856
|
-
const candidate =
|
|
19657
|
+
const candidate = resolve17(reviewRoot, source);
|
|
18857
19658
|
const relativeToRoot = relative(reviewRoot, candidate);
|
|
18858
19659
|
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || isAbsolute(relativeToRoot)) {
|
|
18859
19660
|
throw new Error(
|
|
@@ -18868,7 +19669,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18868
19669
|
}
|
|
18869
19670
|
}
|
|
18870
19671
|
async function loadReviewInput(components, options = {}) {
|
|
18871
|
-
const reviewRoot =
|
|
19672
|
+
const reviewRoot = resolve17(options.reviewRoot ?? process.cwd());
|
|
18872
19673
|
const records = await Promise.all(
|
|
18873
19674
|
components.map(async (component) => {
|
|
18874
19675
|
let resolvedSourcePath;
|
|
@@ -18899,7 +19700,7 @@ var init_parser = __esm({
|
|
|
18899
19700
|
});
|
|
18900
19701
|
|
|
18901
19702
|
// packages/experience-design-system-cli-legacy/src/analyze/select/command.ts
|
|
18902
|
-
import { access as access6, readFile as
|
|
19703
|
+
import { access as access6, readFile as readFile18 } from "node:fs/promises";
|
|
18903
19704
|
async function loadAndValidateForReview(sessionId2, projectRoot) {
|
|
18904
19705
|
const db = openPipelineDb();
|
|
18905
19706
|
let rawComponents;
|
|
@@ -18917,7 +19718,7 @@ async function patchReviewStateWithValidationErrors(sessionId2, errors, opts = {
|
|
|
18917
19718
|
let snapshot;
|
|
18918
19719
|
try {
|
|
18919
19720
|
await access6(paths.statePath);
|
|
18920
|
-
snapshot = JSON.parse(await
|
|
19721
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18921
19722
|
} catch {
|
|
18922
19723
|
snapshot = await loadAndValidateForReview(sessionId2, void 0);
|
|
18923
19724
|
snapshot = await ensureRefineSession(sessionId2, artifactsRoot, snapshot);
|
|
@@ -18968,7 +19769,7 @@ async function rejectComponentsByName(sessionId2, names, opts = {}) {
|
|
|
18968
19769
|
const nameSet = new Set(names);
|
|
18969
19770
|
let snapshot;
|
|
18970
19771
|
try {
|
|
18971
|
-
snapshot = JSON.parse(await
|
|
19772
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18972
19773
|
} catch {
|
|
18973
19774
|
return;
|
|
18974
19775
|
}
|
|
@@ -19067,9 +19868,9 @@ function spawnGenerateChild(opts) {
|
|
|
19067
19868
|
stderr += chunk;
|
|
19068
19869
|
opts.onStderr?.(chunk);
|
|
19069
19870
|
});
|
|
19070
|
-
const donePromise = new Promise((
|
|
19871
|
+
const donePromise = new Promise((resolve21) => {
|
|
19071
19872
|
child.on("close", (code, signal) => {
|
|
19072
|
-
|
|
19873
|
+
resolve21({
|
|
19073
19874
|
exitCode: code ?? 0,
|
|
19074
19875
|
signal: signal ?? null,
|
|
19075
19876
|
stdout,
|
|
@@ -19077,7 +19878,7 @@ function spawnGenerateChild(opts) {
|
|
|
19077
19878
|
});
|
|
19078
19879
|
});
|
|
19079
19880
|
child.on("error", (err) => {
|
|
19080
|
-
|
|
19881
|
+
resolve21({
|
|
19081
19882
|
exitCode: 1,
|
|
19082
19883
|
signal: null,
|
|
19083
19884
|
stdout,
|
|
@@ -27215,6 +28016,9 @@ function shouldGenerateAfterCredentialsValidated(opts) {
|
|
|
27215
28016
|
function shouldSkipFinalReviewAfterCredentials(state) {
|
|
27216
28017
|
return state.finalReviewPassed && state.generateSessionId != null;
|
|
27217
28018
|
}
|
|
28019
|
+
function resolveNoCacheForGenerate(opts) {
|
|
28020
|
+
return opts.cliNoCache;
|
|
28021
|
+
}
|
|
27218
28022
|
function shouldBypassPreview(state) {
|
|
27219
28023
|
return state.credentialsSkipped === true;
|
|
27220
28024
|
}
|
|
@@ -27241,43 +28045,70 @@ var init_wizard_state_transitions = __esm({
|
|
|
27241
28045
|
async function runSelectionAgent(options) {
|
|
27242
28046
|
const db = openPipelineDb();
|
|
27243
28047
|
let components;
|
|
28048
|
+
const cachedDecisions = /* @__PURE__ */ new Map();
|
|
28049
|
+
const cliVersion2 = await getCliCacheVersion();
|
|
28050
|
+
const promptHash = await hashPromptForSkill(
|
|
28051
|
+
"select",
|
|
28052
|
+
options.agent,
|
|
28053
|
+
options.model,
|
|
28054
|
+
options.promptPath,
|
|
28055
|
+
[SELECT_PAYLOAD_FORMAT],
|
|
28056
|
+
options.promptText
|
|
28057
|
+
);
|
|
27244
28058
|
try {
|
|
27245
28059
|
components = loadRawComponents(db, options.sessionId);
|
|
28060
|
+
if (!options.noCache) {
|
|
28061
|
+
for (const component of components) {
|
|
28062
|
+
const componentHash = hashComponentShape(component);
|
|
28063
|
+
const cached = lookupSelectCache(db, componentHash, promptHash, cliVersion2);
|
|
28064
|
+
if (cached) {
|
|
28065
|
+
cachedDecisions.set(component.name, {
|
|
28066
|
+
decision: cached.decision,
|
|
28067
|
+
reason: cached.reason
|
|
28068
|
+
});
|
|
28069
|
+
}
|
|
28070
|
+
}
|
|
28071
|
+
}
|
|
27246
28072
|
} finally {
|
|
27247
28073
|
db.close();
|
|
27248
28074
|
}
|
|
27249
28075
|
if (components.length === 0) return;
|
|
27250
|
-
const
|
|
27251
|
-
|
|
27252
|
-
|
|
27253
|
-
|
|
27254
|
-
|
|
27255
|
-
|
|
27256
|
-
|
|
27257
|
-
|
|
27258
|
-
|
|
27259
|
-
|
|
27260
|
-
|
|
27261
|
-
|
|
27262
|
-
|
|
27263
|
-
|
|
27264
|
-
|
|
27265
|
-
|
|
27266
|
-
|
|
27267
|
-
|
|
27268
|
-
|
|
27269
|
-
|
|
27270
|
-
|
|
27271
|
-
|
|
27272
|
-
|
|
27273
|
-
|
|
27274
|
-
|
|
27275
|
-
|
|
27276
|
-
|
|
27277
|
-
|
|
27278
|
-
|
|
28076
|
+
const componentsToRun = components.filter((component) => !cachedDecisions.has(component.name));
|
|
28077
|
+
let calls = [];
|
|
28078
|
+
if (componentsToRun.length > 0) {
|
|
28079
|
+
const invoker2 = createLocalCliAgentInvoker({
|
|
28080
|
+
onDebugEvent: (name, payload) => getDebugLogger().event("agent", name, payload)
|
|
28081
|
+
});
|
|
28082
|
+
const selectBuckets = bucketComponentsProps(componentsToRun);
|
|
28083
|
+
for (const assignment of selectBuckets) {
|
|
28084
|
+
getDebugLogger().event("analyze", "prop-buckets.select", { ...assignment });
|
|
28085
|
+
}
|
|
28086
|
+
const prompt = await buildPrompt({
|
|
28087
|
+
skill: "select",
|
|
28088
|
+
mode: "autonomous",
|
|
28089
|
+
rawComponentsInline: JSON.stringify(
|
|
28090
|
+
componentsToRun.map((component) => ({ ...component, props: component.props.map(stripPropProvenance) })),
|
|
28091
|
+
null,
|
|
28092
|
+
2
|
|
28093
|
+
),
|
|
28094
|
+
propBucketsInline: JSON.stringify(selectBuckets),
|
|
28095
|
+
outDir: process.cwd(),
|
|
28096
|
+
...options.promptText !== void 0 ? { skillContentOverride: options.promptText } : {},
|
|
28097
|
+
...options.promptText === void 0 && options.promptPath ? { skillPathOverride: options.promptPath } : {}
|
|
28098
|
+
});
|
|
28099
|
+
const { result } = await invokeAgentWithOutput(
|
|
28100
|
+
invoker2,
|
|
28101
|
+
{ agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
|
|
28102
|
+
false
|
|
28103
|
+
);
|
|
28104
|
+
if (result.timedOut) throw new Error("selection agent timed out");
|
|
28105
|
+
if (result.exitCode !== 0) throw new Error(`selection agent exited with code ${result.exitCode}`);
|
|
28106
|
+
const parsed = parseSelectToolCallLines(result.stdout);
|
|
28107
|
+
for (const warning of parsed.warnings) process.stderr.write(`Warning: selection agent: ${warning}
|
|
27279
28108
|
`);
|
|
27280
|
-
|
|
28109
|
+
calls = parsed.calls;
|
|
28110
|
+
}
|
|
28111
|
+
const byName = new Map(calls.map((call) => [call.name, call]));
|
|
27281
28112
|
const writeDb = openPipelineDb();
|
|
27282
28113
|
try {
|
|
27283
28114
|
writeDb.exec("BEGIN");
|
|
@@ -27285,15 +28116,27 @@ async function runSelectionAgent(options) {
|
|
|
27285
28116
|
`UPDATE raw_components SET status = ?, reject_reason = ? WHERE session_id = ? AND component_id = ?`
|
|
27286
28117
|
);
|
|
27287
28118
|
for (const component of components) {
|
|
28119
|
+
const cached = cachedDecisions.get(component.name);
|
|
27288
28120
|
const call = byName.get(component.name);
|
|
27289
|
-
if (!call) continue;
|
|
27290
|
-
const rejected = call.tool === "reject_component";
|
|
28121
|
+
if (!cached && !call) continue;
|
|
28122
|
+
const rejected = cached ? cached.decision === "rejected" : call.tool === "reject_component";
|
|
28123
|
+
const reason = cached ? cached.reason : call.reason ?? null;
|
|
27291
28124
|
update.run(
|
|
27292
28125
|
rejected ? "rejected" : "accepted",
|
|
27293
|
-
rejected ?
|
|
28126
|
+
rejected ? reason : null,
|
|
27294
28127
|
options.sessionId,
|
|
27295
28128
|
component.component_id
|
|
27296
28129
|
);
|
|
28130
|
+
if (!cached) {
|
|
28131
|
+
storeSelectCache(
|
|
28132
|
+
writeDb,
|
|
28133
|
+
hashComponentShape(component),
|
|
28134
|
+
promptHash,
|
|
28135
|
+
cliVersion2,
|
|
28136
|
+
rejected ? "rejected" : "accepted",
|
|
28137
|
+
rejected ? reason : null
|
|
28138
|
+
);
|
|
28139
|
+
}
|
|
27297
28140
|
}
|
|
27298
28141
|
writeDb.exec("COMMIT");
|
|
27299
28142
|
} catch (error) {
|
|
@@ -27303,7 +28146,7 @@ async function runSelectionAgent(options) {
|
|
|
27303
28146
|
writeDb.close();
|
|
27304
28147
|
}
|
|
27305
28148
|
}
|
|
27306
|
-
var DEFAULT_TIMEOUT_MS4;
|
|
28149
|
+
var SELECT_PAYLOAD_FORMAT, DEFAULT_TIMEOUT_MS4;
|
|
27307
28150
|
var init_run_selection_agent = __esm({
|
|
27308
28151
|
"packages/experience-design-system-cli-legacy/src/import/tui/run-selection-agent.ts"() {
|
|
27309
28152
|
"use strict";
|
|
@@ -27312,6 +28155,8 @@ var init_run_selection_agent = __esm({
|
|
|
27312
28155
|
init_debug_logger();
|
|
27313
28156
|
init_agent_output();
|
|
27314
28157
|
init_db();
|
|
28158
|
+
init_cache_keys();
|
|
28159
|
+
SELECT_PAYLOAD_FORMAT = "prop-buckets-v1";
|
|
27315
28160
|
DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
|
|
27316
28161
|
}
|
|
27317
28162
|
});
|
|
@@ -27330,7 +28175,7 @@ __export(WizardApp_exports, {
|
|
|
27330
28175
|
});
|
|
27331
28176
|
import { useEffect as useEffect15, useRef as useRef10, useState as useState23 } from "react";
|
|
27332
28177
|
import { Box as Box42, Text as Text46 } from "ink";
|
|
27333
|
-
import { join as join23, resolve as
|
|
28178
|
+
import { join as join23, resolve as resolve18 } from "node:path";
|
|
27334
28179
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27335
28180
|
import { access as access7, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
27336
28181
|
import { tmpdir } from "node:os";
|
|
@@ -27343,21 +28188,28 @@ function buildGenerateComponentsArgs(opts) {
|
|
|
27343
28188
|
if (opts.tokensPath) args.push("--tokens", opts.tokensPath);
|
|
27344
28189
|
if (opts.model) args.push("--model", opts.model);
|
|
27345
28190
|
if (opts.bedrock) args.push("--bedrock");
|
|
28191
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27346
28192
|
if (opts.generatePromptPath) args.push("--generate-prompt-path", opts.generatePromptPath);
|
|
27347
28193
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27348
28194
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
28195
|
+
if (opts.restoreCache) args.push("--restore-cache");
|
|
28196
|
+
if (opts.cachedComponents && opts.cachedComponents.length > 0) {
|
|
28197
|
+
args.push("--cached-components", JSON.stringify(opts.cachedComponents));
|
|
28198
|
+
}
|
|
27349
28199
|
return args;
|
|
27350
28200
|
}
|
|
27351
28201
|
function buildGenerateTokensArgs(opts) {
|
|
27352
28202
|
const args = [findCliPath(), "__generate", "tokens", "--agent", opts.agent, "--raw-tokens", opts.rawTokensPath];
|
|
27353
28203
|
if (opts.model) args.push("--model", opts.model);
|
|
27354
28204
|
if (opts.bedrock) args.push("--bedrock");
|
|
28205
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27355
28206
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27356
28207
|
return args;
|
|
27357
28208
|
}
|
|
27358
28209
|
function buildMapTokensArgs(opts) {
|
|
27359
28210
|
const args = ["map", "tokens", "--session", opts.sessionId, "--agent", opts.agent];
|
|
27360
28211
|
if (opts.model) args.push("--model", opts.model);
|
|
28212
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27361
28213
|
if (opts.skipAgent) args.push("--skip-agent");
|
|
27362
28214
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27363
28215
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
@@ -27449,6 +28301,7 @@ function WizardApp({
|
|
|
27449
28301
|
initialProjectPath,
|
|
27450
28302
|
host,
|
|
27451
28303
|
promptOverrides,
|
|
28304
|
+
noCache = false,
|
|
27452
28305
|
livePreview = true,
|
|
27453
28306
|
generatePromptPath,
|
|
27454
28307
|
skipMapTokens = false,
|
|
@@ -27473,6 +28326,7 @@ function WizardApp({
|
|
|
27473
28326
|
});
|
|
27474
28327
|
const allowEmptyDeleteAllRef = useRef10(false);
|
|
27475
28328
|
const generateChildRef = useRef10(null);
|
|
28329
|
+
const generationCachePreflightRef = useRef10(null);
|
|
27476
28330
|
const selectionToReviewStartedAtRef = useRef10(null);
|
|
27477
28331
|
const credentialsValidationIdRef = useRef10(0);
|
|
27478
28332
|
const pendingCredentialValidationRef = useRef10(null);
|
|
@@ -27487,8 +28341,9 @@ function WizardApp({
|
|
|
27487
28341
|
const existingEntitiesPromiseRef = useRef10(null);
|
|
27488
28342
|
const generatePromiseRef = useRef10(null);
|
|
27489
28343
|
const rawTokensEntryReady = !!initialRawTokensPath;
|
|
28344
|
+
const effectiveNoCache = resolveNoCacheForGenerate({ cliNoCache: noCache });
|
|
27490
28345
|
const initialStepResolved = rawTokensEntryReady ? initialProjectPath ? "path-validation" : "credentials" : initialProjectPath ? "token-input" : "welcome";
|
|
27491
|
-
const initialOutDir = initialProjectPath ? join23(
|
|
28346
|
+
const initialOutDir = initialProjectPath ? join23(resolve18(initialProjectPath), ".contentful") : "";
|
|
27492
28347
|
const [state, setState] = useState23({
|
|
27493
28348
|
step: initialStepResolved,
|
|
27494
28349
|
agent: initialAgent ?? "claude",
|
|
@@ -27664,13 +28519,14 @@ If you are using AWS Bedrock, run:
|
|
|
27664
28519
|
if (!deferStep) update({ step: nextStep });
|
|
27665
28520
|
return true;
|
|
27666
28521
|
};
|
|
27667
|
-
const runGenerateTokens = async (rawTokensPath, outDir) => {
|
|
28522
|
+
const runGenerateTokens = async (rawTokensPath, outDir, forceRegenerate = false) => {
|
|
27668
28523
|
update({ tokenGenerationStatus: "running" });
|
|
27669
28524
|
const tokenArgs = buildGenerateTokensArgs({
|
|
27670
28525
|
rawTokensPath,
|
|
27671
28526
|
agent: state.agent,
|
|
27672
28527
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27673
28528
|
...state.bedrock ? { bedrock: true } : {},
|
|
28529
|
+
noCache: effectiveNoCache || forceRegenerate,
|
|
27674
28530
|
promptOverrides
|
|
27675
28531
|
});
|
|
27676
28532
|
const result = await runSpawnedCli(tokenArgs);
|
|
@@ -27719,6 +28575,7 @@ If you are using AWS Bedrock, run:
|
|
|
27719
28575
|
const timer = startWizardTimer("token-mapping", {
|
|
27720
28576
|
sessionId: sessionId2,
|
|
27721
28577
|
silent,
|
|
28578
|
+
noCache: effectiveNoCache,
|
|
27722
28579
|
skipAgent: skipMapTokens
|
|
27723
28580
|
});
|
|
27724
28581
|
let mappablePropCount = 0;
|
|
@@ -27727,7 +28584,7 @@ If you are using AWS Bedrock, run:
|
|
|
27727
28584
|
const db = openPipelineDb();
|
|
27728
28585
|
try {
|
|
27729
28586
|
if (state.tokenSessionId && state.tokenSessionId !== sessionId2) {
|
|
27730
|
-
|
|
28587
|
+
copyTokensFromCache(db, state.tokenSessionId, sessionId2);
|
|
27731
28588
|
} else if (!state.tokenSessionId && state.tokensPath) {
|
|
27732
28589
|
const tokens = await readTokensFromPath("tokens", state.tokensPath);
|
|
27733
28590
|
storeDtcgTokens(db, sessionId2, [], tokens);
|
|
@@ -27767,6 +28624,7 @@ If you are using AWS Bedrock, run:
|
|
|
27767
28624
|
sessionId: sessionId2,
|
|
27768
28625
|
agent: state.agent,
|
|
27769
28626
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28627
|
+
noCache: effectiveNoCache,
|
|
27770
28628
|
skipAgent: skipMapTokens,
|
|
27771
28629
|
promptOverrides,
|
|
27772
28630
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
|
|
@@ -27846,7 +28704,7 @@ If you are using AWS Bedrock, run:
|
|
|
27846
28704
|
return promise;
|
|
27847
28705
|
};
|
|
27848
28706
|
const runExtract = async (projectPath, showProgress = true) => {
|
|
27849
|
-
const outDir = join23(
|
|
28707
|
+
const outDir = join23(resolve18(projectPath), ".contentful");
|
|
27850
28708
|
const existingEntitiesExpected = !state.credentialsSkipped && Boolean(state.spaceId && state.environmentId && state.cmaToken && projectPath);
|
|
27851
28709
|
update({
|
|
27852
28710
|
...showProgress ? { step: "extracting" } : {},
|
|
@@ -27861,6 +28719,7 @@ If you are using AWS Bedrock, run:
|
|
|
27861
28719
|
});
|
|
27862
28720
|
const existingEntitiesPromise = startExistingEntitiesFetch(projectPath, outDir);
|
|
27863
28721
|
const extractArgs = [findCliPath(), "__extract", "--project", projectPath];
|
|
28722
|
+
if (effectiveNoCache) extractArgs.push("--no-cache");
|
|
27864
28723
|
let selectionPromptText;
|
|
27865
28724
|
let selectionPromptPath;
|
|
27866
28725
|
try {
|
|
@@ -27869,7 +28728,7 @@ If you are using AWS Bedrock, run:
|
|
|
27869
28728
|
const selectOverride = overrides.get("select");
|
|
27870
28729
|
if (selectOverride?.kind === "text") selectionPromptText = selectOverride.value;
|
|
27871
28730
|
if (selectOverride?.kind === "path") {
|
|
27872
|
-
selectionPromptPath =
|
|
28731
|
+
selectionPromptPath = resolve18(selectOverride.value);
|
|
27873
28732
|
await resolvePromptOverride(selectOverride);
|
|
27874
28733
|
}
|
|
27875
28734
|
} catch (error) {
|
|
@@ -27893,7 +28752,8 @@ If you are using AWS Bedrock, run:
|
|
|
27893
28752
|
agent: state.agent,
|
|
27894
28753
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27895
28754
|
...selectionPromptText !== void 0 ? { promptText: selectionPromptText } : {},
|
|
27896
|
-
...selectionPromptPath ? { promptPath: selectionPromptPath } : {}
|
|
28755
|
+
...selectionPromptPath ? { promptPath: selectionPromptPath } : {},
|
|
28756
|
+
noCache: effectiveNoCache
|
|
27897
28757
|
});
|
|
27898
28758
|
})().catch((error) => {
|
|
27899
28759
|
selectionError = error;
|
|
@@ -28038,17 +28898,136 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28038
28898
|
generateProgress: null
|
|
28039
28899
|
}));
|
|
28040
28900
|
};
|
|
28041
|
-
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2) => ({
|
|
28901
|
+
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => ({
|
|
28042
28902
|
sessionId: extractSessionId,
|
|
28043
28903
|
tokensPath,
|
|
28044
28904
|
agent: state.agent,
|
|
28045
28905
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28046
28906
|
...state.bedrock ? { bedrock: true } : {},
|
|
28907
|
+
noCache: effectiveNoCache,
|
|
28047
28908
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {},
|
|
28048
28909
|
...generatePromptPath2 ? { generatePromptPath: generatePromptPath2 } : {},
|
|
28049
|
-
promptOverrides
|
|
28910
|
+
promptOverrides,
|
|
28911
|
+
...cachedComponents && cachedComponents.length > 0 ? { cachedComponents } : {}
|
|
28050
28912
|
});
|
|
28051
|
-
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2));
|
|
28913
|
+
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents));
|
|
28914
|
+
const buildGenerateCliArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateComponentsArgs(
|
|
28915
|
+
buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents)
|
|
28916
|
+
);
|
|
28917
|
+
const checkGenerateCache = async (extractSessionId, tokensPath) => {
|
|
28918
|
+
const timer = startWizardTimer("generation-cache-status", {
|
|
28919
|
+
sessionId: extractSessionId,
|
|
28920
|
+
noCache: effectiveNoCache
|
|
28921
|
+
});
|
|
28922
|
+
if (effectiveNoCache) {
|
|
28923
|
+
finishWizardTimer("generation-cache-status", timer, { status: "skipped" });
|
|
28924
|
+
return false;
|
|
28925
|
+
}
|
|
28926
|
+
const result = await runCli([...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"]);
|
|
28927
|
+
const hit = result.exitCode === 0 && /^cache-status=hit$/m.test(result.stdout);
|
|
28928
|
+
finishWizardTimer("generation-cache-status", timer, {
|
|
28929
|
+
status: hit ? "hit" : "miss",
|
|
28930
|
+
exitCode: result.exitCode,
|
|
28931
|
+
...result.exitCode !== 0 ? { stderrTail: result.stderr.trim().slice(-500) } : {}
|
|
28932
|
+
});
|
|
28933
|
+
return hit;
|
|
28934
|
+
};
|
|
28935
|
+
const checkGenerateCacheComponents = async (extractSessionId, tokensPath, restoreCache = false) => {
|
|
28936
|
+
const timer = startWizardTimer("generation-cache-components", {
|
|
28937
|
+
sessionId: extractSessionId,
|
|
28938
|
+
restoreCache,
|
|
28939
|
+
noCache: effectiveNoCache
|
|
28940
|
+
});
|
|
28941
|
+
if (effectiveNoCache) {
|
|
28942
|
+
finishWizardTimer("generation-cache-components", timer, { status: "skipped" });
|
|
28943
|
+
return /* @__PURE__ */ new Set();
|
|
28944
|
+
}
|
|
28945
|
+
const args = [...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"];
|
|
28946
|
+
if (restoreCache) args.push("--restore-cache");
|
|
28947
|
+
const result = await runCli(args);
|
|
28948
|
+
if (result.exitCode !== 0) {
|
|
28949
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28950
|
+
status: "error",
|
|
28951
|
+
exitCode: result.exitCode,
|
|
28952
|
+
stderrTail: result.stderr.trim().slice(-500)
|
|
28953
|
+
});
|
|
28954
|
+
return /* @__PURE__ */ new Set();
|
|
28955
|
+
}
|
|
28956
|
+
const line = /^cache-components=(.+)$/m.exec(result.stdout)?.[1];
|
|
28957
|
+
if (!line) {
|
|
28958
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28959
|
+
status: "missing-output",
|
|
28960
|
+
exitCode: result.exitCode,
|
|
28961
|
+
cachedCount: 0
|
|
28962
|
+
});
|
|
28963
|
+
return /* @__PURE__ */ new Set();
|
|
28964
|
+
}
|
|
28965
|
+
try {
|
|
28966
|
+
const names = JSON.parse(line);
|
|
28967
|
+
const cachedNames = new Set(
|
|
28968
|
+
Array.isArray(names) ? names.filter((name) => typeof name === "string") : []
|
|
28969
|
+
);
|
|
28970
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28971
|
+
status: "complete",
|
|
28972
|
+
exitCode: result.exitCode,
|
|
28973
|
+
cachedCount: cachedNames.size
|
|
28974
|
+
});
|
|
28975
|
+
return cachedNames;
|
|
28976
|
+
} catch {
|
|
28977
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28978
|
+
status: "invalid-output",
|
|
28979
|
+
exitCode: result.exitCode,
|
|
28980
|
+
cachedCount: 0
|
|
28981
|
+
});
|
|
28982
|
+
return /* @__PURE__ */ new Set();
|
|
28983
|
+
}
|
|
28984
|
+
};
|
|
28985
|
+
useEffect15(() => {
|
|
28986
|
+
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) {
|
|
28987
|
+
return;
|
|
28988
|
+
}
|
|
28989
|
+
const sessionId2 = state.extractSessionId;
|
|
28990
|
+
if (generationCachePreflightRef.current?.sessionId === sessionId2) return;
|
|
28991
|
+
const timer = startWizardTimer("generation-cache-preflight", { sessionId: sessionId2 });
|
|
28992
|
+
const db = openPipelineDb();
|
|
28993
|
+
let generatedNames = null;
|
|
28994
|
+
try {
|
|
28995
|
+
const rows = db.prepare("SELECT name, status FROM raw_components WHERE session_id = ?").all(sessionId2);
|
|
28996
|
+
if (rows.length > 0 && rows.every((row) => row.status === "generated")) {
|
|
28997
|
+
generatedNames = new Set(rows.map((row) => row.name));
|
|
28998
|
+
}
|
|
28999
|
+
} finally {
|
|
29000
|
+
db.close();
|
|
29001
|
+
}
|
|
29002
|
+
if (generatedNames) {
|
|
29003
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: Promise.resolve(generatedNames) };
|
|
29004
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29005
|
+
status: "complete",
|
|
29006
|
+
source: "session-db",
|
|
29007
|
+
cachedCount: generatedNames.size
|
|
29008
|
+
});
|
|
29009
|
+
return;
|
|
29010
|
+
}
|
|
29011
|
+
const promise = checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
29012
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise };
|
|
29013
|
+
void promise.then((cachedNames) => {
|
|
29014
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29015
|
+
status: "complete",
|
|
29016
|
+
source: "cache-status",
|
|
29017
|
+
cachedCount: cachedNames.size
|
|
29018
|
+
});
|
|
29019
|
+
});
|
|
29020
|
+
}, [
|
|
29021
|
+
state.step,
|
|
29022
|
+
state.extractSessionId,
|
|
29023
|
+
state.tokensPath,
|
|
29024
|
+
state.rawTokensPath,
|
|
29025
|
+
state.tokenGenerationStatus,
|
|
29026
|
+
state.selectionAgentStatus,
|
|
29027
|
+
state.compositionPhase,
|
|
29028
|
+
state.existingEntitiesStatus,
|
|
29029
|
+
state.existingEntitiesPath
|
|
29030
|
+
]);
|
|
28052
29031
|
const startGeneratePrefetch = (extractSessionId, tokensPath) => {
|
|
28053
29032
|
const args = buildGenerateArgs(extractSessionId, tokensPath);
|
|
28054
29033
|
let progressCursor = null;
|
|
@@ -28103,13 +29082,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28103
29082
|
});
|
|
28104
29083
|
return donePromise;
|
|
28105
29084
|
};
|
|
28106
|
-
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false) => {
|
|
29085
|
+
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false, cachedComponents = []) => {
|
|
28107
29086
|
const timer = startWizardTimer("component-generation", {
|
|
28108
29087
|
sessionId: extractSessionId,
|
|
28109
29088
|
acceptedCount,
|
|
28110
|
-
suppressScreen
|
|
29089
|
+
suppressScreen,
|
|
29090
|
+
noCache: effectiveNoCache
|
|
28111
29091
|
});
|
|
28112
|
-
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath);
|
|
29092
|
+
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath, cachedComponents);
|
|
28113
29093
|
let progressCursor = state.generateProgress;
|
|
28114
29094
|
const { donePromise } = spawnGenerateChild({
|
|
28115
29095
|
command: "node",
|
|
@@ -28179,6 +29159,25 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28179
29159
|
finishSelectionToReviewTimer("error");
|
|
28180
29160
|
}
|
|
28181
29161
|
};
|
|
29162
|
+
const finishCachedGeneration = async (sessionId2, acceptedCount) => {
|
|
29163
|
+
if (await runMapTokens2(sessionId2, true)) {
|
|
29164
|
+
finishSelectionToReviewTimer("cached");
|
|
29165
|
+
update(
|
|
29166
|
+
{
|
|
29167
|
+
acceptedCount,
|
|
29168
|
+
autoRejectedCount: 0,
|
|
29169
|
+
generateSessionId: sessionId2,
|
|
29170
|
+
generatedCount: acceptedCount,
|
|
29171
|
+
generateProgress: null,
|
|
29172
|
+
mapTokensStatus: "complete",
|
|
29173
|
+
step: "final-review"
|
|
29174
|
+
},
|
|
29175
|
+
{ clearScreen: false }
|
|
29176
|
+
);
|
|
29177
|
+
} else {
|
|
29178
|
+
finishSelectionToReviewTimer("error");
|
|
29179
|
+
}
|
|
29180
|
+
};
|
|
28182
29181
|
const advanceToPushFlow = (generatedAcceptedCount) => {
|
|
28183
29182
|
update({ generatedAcceptedCount });
|
|
28184
29183
|
void runSaveAndPush();
|
|
@@ -28363,8 +29362,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28363
29362
|
}
|
|
28364
29363
|
}
|
|
28365
29364
|
if (await runAgentAuthCheck("generating", true)) {
|
|
28366
|
-
|
|
28367
|
-
|
|
29365
|
+
const cacheHit = await checkGenerateCache(sid, state.tokensPath);
|
|
29366
|
+
if (cacheHit) {
|
|
29367
|
+
update({ step: "generating" });
|
|
29368
|
+
void finishCachedGeneration(sid, state.acceptedCount);
|
|
29369
|
+
} else {
|
|
29370
|
+
update({ step: "generating" });
|
|
29371
|
+
void runGenerate(sid, state.tokensPath, state.acceptedCount);
|
|
29372
|
+
}
|
|
28368
29373
|
}
|
|
28369
29374
|
return;
|
|
28370
29375
|
}
|
|
@@ -28728,7 +29733,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28728
29733
|
});
|
|
28729
29734
|
return { ok: false };
|
|
28730
29735
|
}
|
|
28731
|
-
await new Promise((
|
|
29736
|
+
await new Promise((resolve21) => setTimeout(resolve21, SAVE_CONFIRMATION_DELAY_MS));
|
|
28732
29737
|
update(nextStateAfterPrint({ skipGate: opts.skipGate, componentsPath }));
|
|
28733
29738
|
return { ok: true };
|
|
28734
29739
|
};
|
|
@@ -28805,6 +29810,12 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28805
29810
|
tokenReuseChecked.current = true;
|
|
28806
29811
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28807
29812
|
const existingTokensPath = join23(state.outDir, "tokens.json");
|
|
29813
|
+
if (effectiveNoCache) {
|
|
29814
|
+
tokenGenerationPromiseRef.current = runAgentAuthCheck(tokenNextStep).then(
|
|
29815
|
+
(ok2) => ok2 ? runGenerateTokens(state.rawTokensPath, state.outDir) : false
|
|
29816
|
+
);
|
|
29817
|
+
return;
|
|
29818
|
+
}
|
|
28808
29819
|
(async () => {
|
|
28809
29820
|
try {
|
|
28810
29821
|
await access7(existingTokensPath);
|
|
@@ -28888,7 +29899,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28888
29899
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28889
29900
|
update({ step: tokenNextStep });
|
|
28890
29901
|
if (await runAgentAuthCheck(tokenNextStep)) {
|
|
28891
|
-
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir);
|
|
29902
|
+
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir, true);
|
|
28892
29903
|
}
|
|
28893
29904
|
},
|
|
28894
29905
|
onQuit: () => process.exit(0)
|
|
@@ -28987,6 +29998,29 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28987
29998
|
acceptedCount: decisions.accepted.length,
|
|
28988
29999
|
rejectedCount: decisions.rejected.length
|
|
28989
30000
|
}) : null;
|
|
30001
|
+
const preflight = generationCachePreflightRef.current;
|
|
30002
|
+
const cachePromise = preflight?.sessionId === sessionId2 ? preflight.promise : checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
30003
|
+
if (!preflight || preflight.sessionId !== sessionId2) {
|
|
30004
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: cachePromise };
|
|
30005
|
+
}
|
|
30006
|
+
const cacheWaitStartedAt = startWizardTimer("selection-cache-restoration-wait", {
|
|
30007
|
+
sessionId: sessionId2,
|
|
30008
|
+
preflight: Boolean(preflight?.sessionId === sessionId2)
|
|
30009
|
+
});
|
|
30010
|
+
try {
|
|
30011
|
+
const cachedNames = await cachePromise;
|
|
30012
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30013
|
+
status: "complete",
|
|
30014
|
+
cachedCount: cachedNames.size
|
|
30015
|
+
});
|
|
30016
|
+
} catch (error) {
|
|
30017
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30018
|
+
status: "error",
|
|
30019
|
+
error: error instanceof Error ? error.message : String(error)
|
|
30020
|
+
});
|
|
30021
|
+
finishSelectionToReviewTimer("error");
|
|
30022
|
+
throw error;
|
|
30023
|
+
}
|
|
28990
30024
|
await runScopeGate({
|
|
28991
30025
|
sessionId: sessionId2,
|
|
28992
30026
|
decisions,
|
|
@@ -28995,12 +30029,35 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28995
30029
|
if (shouldGenerateAfterScopeGate({ acceptedCount })) {
|
|
28996
30030
|
const authPromise = runAgentAuthCheck("generating", true);
|
|
28997
30031
|
if (await authPromise) {
|
|
28998
|
-
|
|
28999
|
-
|
|
29000
|
-
|
|
29001
|
-
|
|
30032
|
+
const comparisonStartedAt = startWizardTimer("generation-cache-set-comparison", {
|
|
30033
|
+
sessionId: sid,
|
|
30034
|
+
acceptedCount: decisions?.accepted.length ?? 0
|
|
30035
|
+
});
|
|
30036
|
+
let cachedNames = await cachePromise;
|
|
30037
|
+
const acceptedNames = decisions?.accepted ?? [];
|
|
30038
|
+
let cacheHit = !effectiveNoCache && acceptedNames.length > 0 && acceptedNames.every((name) => cachedNames.has(name));
|
|
30039
|
+
if (!cacheHit && !effectiveNoCache && acceptedNames.length > 0) {
|
|
30040
|
+
cachedNames = await checkGenerateCacheComponents(sid, state.tokensPath, true);
|
|
30041
|
+
cacheHit = acceptedNames.every((name) => cachedNames.has(name));
|
|
30042
|
+
}
|
|
30043
|
+
finishWizardTimer("generation-cache-set-comparison", comparisonStartedAt, {
|
|
30044
|
+
status: "complete",
|
|
30045
|
+
cacheHit,
|
|
30046
|
+
cachedCount: cachedNames.size,
|
|
30047
|
+
acceptedCount: acceptedNames.length
|
|
29002
30048
|
});
|
|
29003
|
-
|
|
30049
|
+
if (cacheHit) {
|
|
30050
|
+
void finishCachedGeneration(sid, acceptedCount);
|
|
30051
|
+
} else {
|
|
30052
|
+
const acceptedNameSet = new Set(acceptedNames);
|
|
30053
|
+
const restoredCachedNames = [...cachedNames].filter((name) => acceptedNameSet.has(name));
|
|
30054
|
+
update({
|
|
30055
|
+
step: "generating",
|
|
30056
|
+
generateProgress: null,
|
|
30057
|
+
acceptedCount
|
|
30058
|
+
});
|
|
30059
|
+
void runGenerate(sid, state.tokensPath, acceptedCount, false, restoredCachedNames);
|
|
30060
|
+
}
|
|
29004
30061
|
} else {
|
|
29005
30062
|
finishSelectionToReviewTimer("error");
|
|
29006
30063
|
}
|
|
@@ -29366,7 +30423,7 @@ function registerImportCommand(program) {
|
|
|
29366
30423
|
"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",
|
|
29367
30424
|
(v, acc) => [...acc, v],
|
|
29368
30425
|
[]
|
|
29369
|
-
).action(async (opts) => {
|
|
30426
|
+
).option("--no-cache", "Re-run all steps even if output already exists").action(async (opts) => {
|
|
29370
30427
|
const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
|
|
29371
30428
|
if (opts.tokens !== void 0) {
|
|
29372
30429
|
const { access: access9 } = await import("node:fs/promises");
|
|
@@ -29403,6 +30460,7 @@ function registerImportCommand(program) {
|
|
|
29403
30460
|
...resolvedModel ? { initialModel: resolvedModel } : {},
|
|
29404
30461
|
initialProjectPath: opts.project !== "." ? normalizePath(opts.project) : void 0,
|
|
29405
30462
|
...buildCompositionForwardingOptions(opts),
|
|
30463
|
+
noCache: opts.cache === false,
|
|
29406
30464
|
skipMapTokens: false,
|
|
29407
30465
|
livePreview: true,
|
|
29408
30466
|
generatePromptPath: creds.generatePromptPath,
|
|
@@ -29490,7 +30548,7 @@ async function pathExists3(path) {
|
|
|
29490
30548
|
return access8(path).then(() => true).catch(() => false);
|
|
29491
30549
|
}
|
|
29492
30550
|
function runSpawn(cmd, args, opts = {}) {
|
|
29493
|
-
return new Promise((
|
|
30551
|
+
return new Promise((resolve21) => {
|
|
29494
30552
|
const child = spawn6(cmd, args, {
|
|
29495
30553
|
cwd: opts.cwd,
|
|
29496
30554
|
env: opts.env ?? process.env,
|
|
@@ -29502,7 +30560,7 @@ function runSpawn(cmd, args, opts = {}) {
|
|
|
29502
30560
|
const settle = (result) => {
|
|
29503
30561
|
if (settled) return;
|
|
29504
30562
|
settled = true;
|
|
29505
|
-
|
|
30563
|
+
resolve21(result);
|
|
29506
30564
|
};
|
|
29507
30565
|
child.on("error", (err) => settle({ exitCode: 1, stdout: "", stderr: err.message }));
|
|
29508
30566
|
child.stdout.on("data", (d) => {
|
|
@@ -30703,13 +31761,13 @@ function PrerequisitesScreen({
|
|
|
30703
31761
|
const driver = {
|
|
30704
31762
|
...base,
|
|
30705
31763
|
emit: (event) => setEvents((current) => [...current, event]),
|
|
30706
|
-
confirm: (question, defaultYes = true) => new Promise((
|
|
31764
|
+
confirm: (question, defaultYes = true) => new Promise((resolve21) => {
|
|
30707
31765
|
setConfirm({
|
|
30708
31766
|
question,
|
|
30709
31767
|
defaultYes,
|
|
30710
31768
|
resolve: (answer) => {
|
|
30711
31769
|
setConfirm(null);
|
|
30712
|
-
|
|
31770
|
+
resolve21(answer);
|
|
30713
31771
|
}
|
|
30714
31772
|
});
|
|
30715
31773
|
})
|
|
@@ -30784,8 +31842,8 @@ function SetupScreen({
|
|
|
30784
31842
|
useEffect21(() => {
|
|
30785
31843
|
if (startedRef.current) return;
|
|
30786
31844
|
startedRef.current = true;
|
|
30787
|
-
const runScreen = (build) => new Promise((
|
|
30788
|
-
setScreen(build(
|
|
31845
|
+
const runScreen = (build) => new Promise((resolve21) => {
|
|
31846
|
+
setScreen(build(resolve21));
|
|
30789
31847
|
});
|
|
30790
31848
|
void (async () => {
|
|
30791
31849
|
const results = [];
|
|
@@ -31393,8 +32451,11 @@ var init_source_call_site_evidence = __esm({
|
|
|
31393
32451
|
});
|
|
31394
32452
|
|
|
31395
32453
|
// packages/experience-design-system-cli-legacy/src/analyze/extract-command.ts
|
|
31396
|
-
import { mkdir as mkdir6, readdir as readdir3, readFile as
|
|
31397
|
-
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as
|
|
32454
|
+
import { mkdir as mkdir6, readdir as readdir3, readFile as readFile19, stat as stat6 } from "node:fs/promises";
|
|
32455
|
+
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as resolve19 } from "node:path";
|
|
32456
|
+
function resolveExtractNoCache(opts) {
|
|
32457
|
+
return opts.noCache === true || opts.cache === false;
|
|
32458
|
+
}
|
|
31398
32459
|
function isDenylistedNoiseFile(name) {
|
|
31399
32460
|
return DENYLISTED_EXACT_FILE_NAMES.has(name) || DENYLISTED_FILE_NAME_PATTERNS.some((pattern) => pattern.test(name));
|
|
31400
32461
|
}
|
|
@@ -31408,12 +32469,12 @@ async function retryDatabaseWrite(operation, attempts = 8) {
|
|
|
31408
32469
|
} catch (error) {
|
|
31409
32470
|
const message = error instanceof Error ? error.message : String(error);
|
|
31410
32471
|
if (!/database is locked|database is busy/i.test(message) || attempt >= attempts) throw error;
|
|
31411
|
-
await new Promise((
|
|
32472
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(250 * attempt, 2e3)));
|
|
31412
32473
|
}
|
|
31413
32474
|
}
|
|
31414
32475
|
}
|
|
31415
32476
|
function resolveFromProjectRoot(projectRoot, inputPath) {
|
|
31416
|
-
return isAbsolute2(inputPath) ? inputPath :
|
|
32477
|
+
return isAbsolute2(inputPath) ? inputPath : resolve19(projectRoot, inputPath);
|
|
31417
32478
|
}
|
|
31418
32479
|
async function pathExists4(path) {
|
|
31419
32480
|
return Boolean(await stat6(path).catch(() => null));
|
|
@@ -31460,7 +32521,7 @@ async function readCandidateFiles(components, extraFiles = []) {
|
|
|
31460
32521
|
await Promise.all(
|
|
31461
32522
|
[...paths].map(async (p) => {
|
|
31462
32523
|
try {
|
|
31463
|
-
const content = await
|
|
32524
|
+
const content = await readFile19(p, "utf8");
|
|
31464
32525
|
out.push({ path: p, content });
|
|
31465
32526
|
} catch {
|
|
31466
32527
|
}
|
|
@@ -31473,7 +32534,8 @@ function registerInternalExtractCommand(program) {
|
|
|
31473
32534
|
"--resolve-unreachable <mode>",
|
|
31474
32535
|
"Retry pass for unresolved Svelte Props types: 'auto' (default), 'always', or 'never'",
|
|
31475
32536
|
"auto"
|
|
31476
|
-
).action(async (opts) => {
|
|
32537
|
+
).option("--no-cache", "Re-run extraction even when all source files are unchanged").action(async (opts) => {
|
|
32538
|
+
const noCache = resolveExtractNoCache(opts);
|
|
31477
32539
|
const resolveUnreachable = (() => {
|
|
31478
32540
|
const v = opts.resolveUnreachable ?? "auto";
|
|
31479
32541
|
if (v !== "auto" && v !== "always" && v !== "never") {
|
|
@@ -31483,7 +32545,7 @@ function registerInternalExtractCommand(program) {
|
|
|
31483
32545
|
}
|
|
31484
32546
|
return v;
|
|
31485
32547
|
})();
|
|
31486
|
-
const projectRoot =
|
|
32548
|
+
const projectRoot = resolve19(opts.project);
|
|
31487
32549
|
const outDir = join27(projectRoot, ".contentful");
|
|
31488
32550
|
let sourceDirectory;
|
|
31489
32551
|
if (opts.dir !== void 0) {
|
|
@@ -31507,16 +32569,50 @@ function registerInternalExtractCommand(program) {
|
|
|
31507
32569
|
process.stderr.write(`progress=scan-done:${sourceFiles.length}
|
|
31508
32570
|
`);
|
|
31509
32571
|
}
|
|
31510
|
-
const
|
|
31511
|
-
|
|
31512
|
-
|
|
32572
|
+
const extractionCacheDb = openPipelineDb();
|
|
32573
|
+
let extraction;
|
|
32574
|
+
let extractionCacheHits = 0;
|
|
32575
|
+
try {
|
|
32576
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32577
|
+
const cachedByPath = /* @__PURE__ */ new Map();
|
|
32578
|
+
if (!noCache && sourceFiles.length > 0) {
|
|
32579
|
+
const hashes = await Promise.all(
|
|
32580
|
+
sourceFiles.map(async (filePath) => [filePath, await hashFile(filePath)])
|
|
32581
|
+
);
|
|
32582
|
+
for (const [filePath, fileHash] of hashes) {
|
|
32583
|
+
cachedByPath.set(filePath, lookupExtractCache(extractionCacheDb, fileHash, cacheVersion));
|
|
32584
|
+
}
|
|
32585
|
+
}
|
|
32586
|
+
const allFilesCached = !noCache && sourceFiles.length > 0 && sourceFiles.every((filePath) => cachedByPath.get(filePath) !== null);
|
|
32587
|
+
if (allFilesCached) {
|
|
32588
|
+
const cachedComponents = sourceFiles.flatMap((filePath) => cachedByPath.get(filePath).components);
|
|
32589
|
+
extractionCacheHits = sourceFiles.length;
|
|
32590
|
+
extraction = { components: cachedComponents, warnings: [], exclusions: [] };
|
|
31513
32591
|
if (!process.stdout.isTTY) {
|
|
31514
|
-
process.stderr.write(
|
|
31515
|
-
`
|
|
32592
|
+
process.stderr.write(
|
|
32593
|
+
`progress=extract:${sourceFiles.length}/${sourceFiles.length}:${cachedComponents.length}
|
|
32594
|
+
`
|
|
32595
|
+
);
|
|
31516
32596
|
}
|
|
31517
|
-
|
|
31518
|
-
|
|
31519
|
-
|
|
32597
|
+
getDebugLogger().event("analyze", "extract.cache-hit", {
|
|
32598
|
+
files: sourceFiles.length,
|
|
32599
|
+
components: cachedComponents.length
|
|
32600
|
+
});
|
|
32601
|
+
} else {
|
|
32602
|
+
extraction = await extractComponents(
|
|
32603
|
+
sourceFiles,
|
|
32604
|
+
({ filesProcessed, componentsFound }) => {
|
|
32605
|
+
if (!process.stdout.isTTY) {
|
|
32606
|
+
process.stderr.write(`progress=extract:${filesProcessed}/${sourceFiles.length}:${componentsFound}
|
|
32607
|
+
`);
|
|
32608
|
+
}
|
|
32609
|
+
},
|
|
32610
|
+
{ resolveUnreachable, projectRoot }
|
|
32611
|
+
);
|
|
32612
|
+
}
|
|
32613
|
+
} finally {
|
|
32614
|
+
extractionCacheDb.close();
|
|
32615
|
+
}
|
|
31520
32616
|
await mkdir6(outDir, { recursive: true });
|
|
31521
32617
|
const db = openPipelineDb();
|
|
31522
32618
|
const { sessionId: sessionId2 } = getOrCreateSession(db, void 0, void 0, {
|
|
@@ -31531,6 +32627,25 @@ function registerInternalExtractCommand(program) {
|
|
|
31531
32627
|
const stepId = createStep(db, sessionId2, "analyze extract", {
|
|
31532
32628
|
project: projectRoot
|
|
31533
32629
|
});
|
|
32630
|
+
if (extractionCacheHits === 0 && !noCache) {
|
|
32631
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32632
|
+
const componentsBySourcePath = /* @__PURE__ */ new Map();
|
|
32633
|
+
for (const component of extraction.components) {
|
|
32634
|
+
if (!component.sourcePath) continue;
|
|
32635
|
+
const components = componentsBySourcePath.get(component.sourcePath) ?? [];
|
|
32636
|
+
components.push(component);
|
|
32637
|
+
componentsBySourcePath.set(component.sourcePath, components);
|
|
32638
|
+
}
|
|
32639
|
+
for (const filePath of sourceFiles) {
|
|
32640
|
+
storeExtractCache(
|
|
32641
|
+
db,
|
|
32642
|
+
filePath,
|
|
32643
|
+
await hashFile(filePath),
|
|
32644
|
+
cacheVersion,
|
|
32645
|
+
componentsBySourcePath.get(filePath) ?? []
|
|
32646
|
+
);
|
|
32647
|
+
}
|
|
32648
|
+
}
|
|
31534
32649
|
const classifiedComponents = extraction.components.map(preClassifyComponent);
|
|
31535
32650
|
for (const exclusion of extraction.exclusions ?? []) {
|
|
31536
32651
|
getDebugLogger().event("filter", "extract.excluded", { ...exclusion });
|
|
@@ -31635,6 +32750,7 @@ var init_extract_command = __esm({
|
|
|
31635
32750
|
"use strict";
|
|
31636
32751
|
init_src2();
|
|
31637
32752
|
init_db();
|
|
32753
|
+
init_cache_keys();
|
|
31638
32754
|
init_cycle_detection();
|
|
31639
32755
|
init_resolve_mapping();
|
|
31640
32756
|
init_manifest_doc_evidence();
|
|
@@ -31733,7 +32849,7 @@ __export(program_exports, {
|
|
|
31733
32849
|
});
|
|
31734
32850
|
import { spawn as spawn7 } from "node:child_process";
|
|
31735
32851
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
31736
|
-
import { dirname as dirname18, join as join28, resolve as
|
|
32852
|
+
import { dirname as dirname18, join as join28, resolve as resolve20 } from "node:path";
|
|
31737
32853
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
31738
32854
|
import { Command } from "commander";
|
|
31739
32855
|
async function runBuild(opts) {
|
|
@@ -31763,7 +32879,7 @@ function resolveBedrockFromAncestors(actionCommand) {
|
|
|
31763
32879
|
}
|
|
31764
32880
|
function registerBuildCommand(program) {
|
|
31765
32881
|
program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").helpOption(false).action(async () => {
|
|
31766
|
-
const pkgRoot =
|
|
32882
|
+
const pkgRoot = resolve20(dirname18(fileURLToPath3(import.meta.url)), "..", "..");
|
|
31767
32883
|
process.stderr.write("\u2699 Building from source...\n");
|
|
31768
32884
|
const { exitCode } = await runBuild({
|
|
31769
32885
|
spawnFn: () => spawn7("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|