@contentful/experience-design-system-cli 2.35.1-dev-build-a91cc5b7.0 → 2.35.1-dev-build-f520d7cb.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/composition/candidate-files.d.ts +34 -0
- package/legacy/dist/src/analyze/composition/composition-cache-key.d.ts +18 -0
- package/legacy/dist/src/analyze/composition/interchange-schema.d.ts +1 -7
- package/legacy/dist/src/analyze/composition/parse-map-edges.d.ts +16 -0
- package/legacy/dist/src/analyze/composition/prompt-loader.d.ts +3 -0
- package/legacy/dist/src/analyze/composition/resolve-mapping-cli.d.ts +10 -0
- package/legacy/dist/src/analyze/composition/resolve-mapping.d.ts +34 -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 +1665 -445
- 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/legacy/prompts/composition-edges.md +11 -0
- package/package.json +3 -7
- package/legacy/dist/src/analyze/composition/source-call-site-evidence.d.ts +0 -30
- 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((resolve22) => {
|
|
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
|
+
resolve22(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((resolve22) => {
|
|
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
|
+
resolve22("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
|
+
resolve22("unauthenticated");
|
|
856
873
|
return;
|
|
857
874
|
}
|
|
858
875
|
try {
|
|
859
876
|
const status = JSON.parse(stdout);
|
|
860
|
-
|
|
877
|
+
resolve22(status.loggedIn ? "ok" : "unauthenticated");
|
|
861
878
|
} catch {
|
|
862
|
-
|
|
879
|
+
resolve22("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((resolve22) => {
|
|
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(() => resolve22(true), () => resolve22(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) => resolve22(code === 0));
|
|
884
901
|
});
|
|
885
902
|
if (!binaryExists2)
|
|
886
903
|
return "not-found";
|
|
@@ -917,6 +934,20 @@ var init_local_cli_agent_invoker = __esm({
|
|
|
917
934
|
});
|
|
918
935
|
|
|
919
936
|
// packages/experience-design-system-generation/dist/src/controller/create-generation-endpoint.js
|
|
937
|
+
function createGenerationEndpoint(options = {}) {
|
|
938
|
+
const invoker2 = createLocalCliAgentInvoker({
|
|
939
|
+
onDebugEvent: options.onDebugEvent
|
|
940
|
+
});
|
|
941
|
+
return {
|
|
942
|
+
async run(request2) {
|
|
943
|
+
validateGenerationRequest(request2);
|
|
944
|
+
return executeGenerationOrchestrator({ ...request2, invoker: invoker2 });
|
|
945
|
+
},
|
|
946
|
+
checkAuth(agent) {
|
|
947
|
+
return invoker2.checkAuth(agent);
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
}
|
|
920
951
|
var init_create_generation_endpoint = __esm({
|
|
921
952
|
"packages/experience-design-system-generation/dist/src/controller/create-generation-endpoint.js"() {
|
|
922
953
|
"use strict";
|
|
@@ -1301,6 +1332,32 @@ var init_progress = __esm({
|
|
|
1301
1332
|
});
|
|
1302
1333
|
|
|
1303
1334
|
// packages/experience-design-system-generation/dist/src/index.js
|
|
1335
|
+
var src_exports = {};
|
|
1336
|
+
__export(src_exports, {
|
|
1337
|
+
AGENT_BINARIES: () => AGENT_BINARIES,
|
|
1338
|
+
AGENT_NAMES: () => AGENT_NAMES,
|
|
1339
|
+
DEFAULT_AGENT_NAME: () => DEFAULT_AGENT_NAME,
|
|
1340
|
+
agentSupportsBedrock: () => agentSupportsBedrock,
|
|
1341
|
+
buildArgs: () => buildAgentArgs,
|
|
1342
|
+
buildPrompt: () => buildPrompt,
|
|
1343
|
+
checkAgentAuth: () => checkAgentAuth,
|
|
1344
|
+
createGenerationEndpoint: () => createGenerationEndpoint,
|
|
1345
|
+
createLocalCliAgentInvoker: () => createLocalCliAgentInvoker,
|
|
1346
|
+
describeAgentFailure: () => describeAgentFailure,
|
|
1347
|
+
executeGenerationOrchestrator: () => executeGenerationOrchestrator,
|
|
1348
|
+
extractSentinelOutput: () => extractSentinelOutput,
|
|
1349
|
+
formatCustomPromptBanner: () => formatCustomPromptBanner,
|
|
1350
|
+
formatGenerateProgressLine: () => formatGenerateProgressLine,
|
|
1351
|
+
isAgentName: () => isAgentName,
|
|
1352
|
+
parseMapTokenPropToolCallLines: () => parseMapTokenPropToolCallLines,
|
|
1353
|
+
parseSelectToolCallLines: () => parseSelectToolCallLines,
|
|
1354
|
+
parseTokenToolCallLines: () => parseTokenToolCallLines,
|
|
1355
|
+
parseToolCallLines: () => parsePropToolCallLines,
|
|
1356
|
+
resolveAgentModel: () => resolveAgentModel,
|
|
1357
|
+
resolveBinary: () => resolveAgentBinary,
|
|
1358
|
+
resolveSkillPath: () => resolveSkillPath,
|
|
1359
|
+
runAgent: () => runAgent
|
|
1360
|
+
});
|
|
1304
1361
|
var init_src = __esm({
|
|
1305
1362
|
"packages/experience-design-system-generation/dist/src/index.js"() {
|
|
1306
1363
|
"use strict";
|
|
@@ -10336,6 +10393,41 @@ var init_read3 = __esm({
|
|
|
10336
10393
|
}
|
|
10337
10394
|
});
|
|
10338
10395
|
|
|
10396
|
+
// packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts
|
|
10397
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
10398
|
+
function hashComponentShape(component) {
|
|
10399
|
+
const payload = {
|
|
10400
|
+
framework: component.framework,
|
|
10401
|
+
name: component.name,
|
|
10402
|
+
source: component.source,
|
|
10403
|
+
props: component.props.map((p) => ({
|
|
10404
|
+
name: p.name,
|
|
10405
|
+
type: p.type
|
|
10406
|
+
})),
|
|
10407
|
+
slots: component.slots.map((s) => ({
|
|
10408
|
+
name: s.name,
|
|
10409
|
+
isDefault: s.isDefault
|
|
10410
|
+
}))
|
|
10411
|
+
};
|
|
10412
|
+
return createHash2("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
10413
|
+
}
|
|
10414
|
+
var init_hash_component_shape = __esm({
|
|
10415
|
+
"packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts"() {
|
|
10416
|
+
"use strict";
|
|
10417
|
+
}
|
|
10418
|
+
});
|
|
10419
|
+
|
|
10420
|
+
// packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts
|
|
10421
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
10422
|
+
function hashTokenContent(rawTokenContent) {
|
|
10423
|
+
return createHash3("sha256").update(rawTokenContent.trim()).digest("hex");
|
|
10424
|
+
}
|
|
10425
|
+
var init_hash_token_content = __esm({
|
|
10426
|
+
"packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts"() {
|
|
10427
|
+
"use strict";
|
|
10428
|
+
}
|
|
10429
|
+
});
|
|
10430
|
+
|
|
10339
10431
|
// packages/experience-design-system-cli-legacy/src/session/repositories/tokens/write.ts
|
|
10340
10432
|
function deleteRawTokensForSession(db, sessionId2) {
|
|
10341
10433
|
db.prepare("DELETE FROM raw_token_groups WHERE session_id = ?").run(sessionId2);
|
|
@@ -10499,17 +10591,47 @@ var init_replace_raw_prop_token_paths = __esm({
|
|
|
10499
10591
|
}
|
|
10500
10592
|
});
|
|
10501
10593
|
|
|
10594
|
+
// packages/experience-design-system-cli-legacy/src/session/cache-keys.ts
|
|
10595
|
+
var cache_keys_exports = {};
|
|
10596
|
+
__export(cache_keys_exports, {
|
|
10597
|
+
hashContent: () => hashContent,
|
|
10598
|
+
hashFile: () => hashFile,
|
|
10599
|
+
hashPromptForSkill: () => hashPromptForSkill
|
|
10600
|
+
});
|
|
10601
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
10602
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
10603
|
+
import { resolve as resolve8 } from "node:path";
|
|
10604
|
+
function hashContent(content) {
|
|
10605
|
+
return createHash4("sha256").update(content).digest("hex");
|
|
10606
|
+
}
|
|
10607
|
+
async function hashFile(filePath) {
|
|
10608
|
+
const content = await readFile7(filePath, "utf8");
|
|
10609
|
+
return hashContent(content);
|
|
10610
|
+
}
|
|
10611
|
+
async function hashPromptForSkill(skill, agent, model, skillPathOverride, extraInputs = [], skillContentOverride) {
|
|
10612
|
+
const promptHash = skillContentOverride ? hashContent(skillContentOverride) : skillPathOverride ? await hashFile(resolve8(skillPathOverride)) : await hashFile(resolveSkillPath(skill));
|
|
10613
|
+
const extraSegment = extraInputs.length > 0 ? `|${extraInputs.join("|")}` : "";
|
|
10614
|
+
return hashContent(`${promptHash}|${agent}|${model ?? ""}${extraSegment}`);
|
|
10615
|
+
}
|
|
10616
|
+
var init_cache_keys = __esm({
|
|
10617
|
+
"packages/experience-design-system-cli-legacy/src/session/cache-keys.ts"() {
|
|
10618
|
+
"use strict";
|
|
10619
|
+
init_src();
|
|
10620
|
+
}
|
|
10621
|
+
});
|
|
10622
|
+
|
|
10502
10623
|
// packages/experience-design-system-cli-legacy/src/session/db.ts
|
|
10503
10624
|
import { DatabaseSync } from "node:sqlite";
|
|
10504
10625
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
10505
|
-
import { readFile as
|
|
10626
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
10627
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
10506
10628
|
import { homedir as homedir3 } from "node:os";
|
|
10507
|
-
import { dirname as dirname14, resolve as
|
|
10629
|
+
import { dirname as dirname14, resolve as resolve9 } from "node:path";
|
|
10508
10630
|
function getPipelineDbPath() {
|
|
10509
10631
|
if (process.env.EDS_PIPELINE_DB_PATH) {
|
|
10510
|
-
return
|
|
10632
|
+
return resolve9(process.env.EDS_PIPELINE_DB_PATH);
|
|
10511
10633
|
}
|
|
10512
|
-
return
|
|
10634
|
+
return resolve9(homedir3(), ".contentful", "experience-design-system-cli", "pipeline.db");
|
|
10513
10635
|
}
|
|
10514
10636
|
function openPipelineDb(dbPath) {
|
|
10515
10637
|
const path = dbPath ?? getPipelineDbPath();
|
|
@@ -10643,8 +10765,134 @@ function applyDbMigrations(db) {
|
|
|
10643
10765
|
if (!rawSlotColsForRationale.some((c2) => c2.name === "rationale")) {
|
|
10644
10766
|
db.exec("ALTER TABLE raw_slots ADD COLUMN rationale TEXT");
|
|
10645
10767
|
}
|
|
10646
|
-
|
|
10647
|
-
|
|
10768
|
+
const hasExtractCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='extract_cache'`).all();
|
|
10769
|
+
if (hasExtractCache.length === 0) {
|
|
10770
|
+
db.exec(`
|
|
10771
|
+
CREATE TABLE extract_cache (
|
|
10772
|
+
file_path TEXT NOT NULL,
|
|
10773
|
+
file_hash TEXT NOT NULL,
|
|
10774
|
+
cli_version TEXT NOT NULL,
|
|
10775
|
+
created_at TEXT NOT NULL,
|
|
10776
|
+
updated_at TEXT NOT NULL,
|
|
10777
|
+
components_json TEXT NOT NULL,
|
|
10778
|
+
PRIMARY KEY (file_hash, cli_version)
|
|
10779
|
+
);
|
|
10780
|
+
CREATE INDEX idx_extract_cache_file ON extract_cache(file_path);
|
|
10781
|
+
`);
|
|
10782
|
+
}
|
|
10783
|
+
const hasSelectCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='select_cache'`).all();
|
|
10784
|
+
if (hasSelectCache.length === 0) {
|
|
10785
|
+
db.exec(`
|
|
10786
|
+
CREATE TABLE select_cache (
|
|
10787
|
+
component_hash TEXT NOT NULL,
|
|
10788
|
+
prompt_hash TEXT NOT NULL,
|
|
10789
|
+
cli_version TEXT NOT NULL,
|
|
10790
|
+
decision TEXT NOT NULL CHECK (decision IN ('accepted','rejected')),
|
|
10791
|
+
reason TEXT,
|
|
10792
|
+
created_at TEXT NOT NULL,
|
|
10793
|
+
updated_at TEXT NOT NULL,
|
|
10794
|
+
PRIMARY KEY (component_hash, prompt_hash, cli_version)
|
|
10795
|
+
);
|
|
10796
|
+
`);
|
|
10797
|
+
}
|
|
10798
|
+
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='generation_cache'`).all();
|
|
10799
|
+
if (tables.length === 0) {
|
|
10800
|
+
db.exec(`
|
|
10801
|
+
CREATE TABLE generation_cache (
|
|
10802
|
+
input_hash TEXT NOT NULL,
|
|
10803
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10804
|
+
entity_id TEXT NOT NULL,
|
|
10805
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10806
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10807
|
+
created_at TEXT NOT NULL,
|
|
10808
|
+
updated_at TEXT NOT NULL,
|
|
10809
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
10810
|
+
);
|
|
10811
|
+
CREATE INDEX idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10812
|
+
CREATE INDEX idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10813
|
+
`);
|
|
10814
|
+
}
|
|
10815
|
+
const genCacheCols = db.prepare(`PRAGMA table_info(generation_cache)`).all();
|
|
10816
|
+
const hasPromptHash = genCacheCols.some((c2) => c2.name === "prompt_hash");
|
|
10817
|
+
const oldPkCols = genCacheCols.filter((c2) => c2.pk > 0).map((c2) => c2.name);
|
|
10818
|
+
const promptHashInPk = oldPkCols.includes("prompt_hash");
|
|
10819
|
+
if (!hasPromptHash) {
|
|
10820
|
+
db.exec(`ALTER TABLE generation_cache ADD COLUMN prompt_hash TEXT NOT NULL DEFAULT ''`);
|
|
10821
|
+
}
|
|
10822
|
+
if (!promptHashInPk) {
|
|
10823
|
+
db.exec("BEGIN");
|
|
10824
|
+
try {
|
|
10825
|
+
db.exec(`
|
|
10826
|
+
CREATE TABLE generation_cache__new (
|
|
10827
|
+
input_hash TEXT NOT NULL,
|
|
10828
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10829
|
+
entity_id TEXT NOT NULL,
|
|
10830
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10831
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10832
|
+
created_at TEXT NOT NULL,
|
|
10833
|
+
updated_at TEXT NOT NULL,
|
|
10834
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10835
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10836
|
+
);
|
|
10837
|
+
INSERT INTO generation_cache__new
|
|
10838
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10839
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10840
|
+
FROM generation_cache;
|
|
10841
|
+
DROP TABLE generation_cache;
|
|
10842
|
+
ALTER TABLE generation_cache__new RENAME TO generation_cache;
|
|
10843
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10844
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10845
|
+
`);
|
|
10846
|
+
db.exec("COMMIT");
|
|
10847
|
+
} catch (e) {
|
|
10848
|
+
db.exec("ROLLBACK");
|
|
10849
|
+
throw e;
|
|
10850
|
+
}
|
|
10851
|
+
}
|
|
10852
|
+
const genCacheTableSql = db.prepare(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'generation_cache'`).get();
|
|
10853
|
+
const hasTokenMappingEntityType = genCacheTableSql?.sql.includes("'token_mapping'") ?? true;
|
|
10854
|
+
if (!hasTokenMappingEntityType) {
|
|
10855
|
+
db.exec("BEGIN");
|
|
10856
|
+
try {
|
|
10857
|
+
db.exec(`
|
|
10858
|
+
CREATE TABLE generation_cache__new2 (
|
|
10859
|
+
input_hash TEXT NOT NULL,
|
|
10860
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10861
|
+
entity_id TEXT NOT NULL,
|
|
10862
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10863
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10864
|
+
created_at TEXT NOT NULL,
|
|
10865
|
+
updated_at TEXT NOT NULL,
|
|
10866
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10867
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10868
|
+
);
|
|
10869
|
+
INSERT INTO generation_cache__new2
|
|
10870
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10871
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10872
|
+
FROM generation_cache;
|
|
10873
|
+
DROP TABLE generation_cache;
|
|
10874
|
+
ALTER TABLE generation_cache__new2 RENAME TO generation_cache;
|
|
10875
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10876
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10877
|
+
`);
|
|
10878
|
+
db.exec("COMMIT");
|
|
10879
|
+
} catch (e) {
|
|
10880
|
+
db.exec("ROLLBACK");
|
|
10881
|
+
throw e;
|
|
10882
|
+
}
|
|
10883
|
+
}
|
|
10884
|
+
const hasCompositionCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='composition_cache'`).all();
|
|
10885
|
+
if (hasCompositionCache.length === 0) {
|
|
10886
|
+
db.exec(`
|
|
10887
|
+
CREATE TABLE composition_cache (
|
|
10888
|
+
input_hash TEXT NOT NULL,
|
|
10889
|
+
cli_version TEXT NOT NULL,
|
|
10890
|
+
agent_output TEXT NOT NULL,
|
|
10891
|
+
created_at TEXT NOT NULL,
|
|
10892
|
+
updated_at TEXT NOT NULL,
|
|
10893
|
+
PRIMARY KEY (input_hash, cli_version)
|
|
10894
|
+
);
|
|
10895
|
+
`);
|
|
10648
10896
|
}
|
|
10649
10897
|
}
|
|
10650
10898
|
function loadComponentReviewMetadata(db, sessionId2, componentName) {
|
|
@@ -11180,16 +11428,16 @@ function extractRelativeImportPaths(sourceText) {
|
|
|
11180
11428
|
return [...specifiers];
|
|
11181
11429
|
}
|
|
11182
11430
|
async function resolveRelativeImport(specifier, fromDir) {
|
|
11183
|
-
const basePath =
|
|
11431
|
+
const basePath = resolve9(fromDir, specifier);
|
|
11184
11432
|
const candidates = [
|
|
11185
11433
|
basePath,
|
|
11186
11434
|
...rewrittenSourcePaths(basePath),
|
|
11187
11435
|
...SIBLING_FILE_EXTENSIONS.map((ext) => `${basePath}${ext}`),
|
|
11188
|
-
...SIBLING_FILE_EXTENSIONS.map((ext) =>
|
|
11436
|
+
...SIBLING_FILE_EXTENSIONS.map((ext) => resolve9(basePath, `index${ext}`))
|
|
11189
11437
|
];
|
|
11190
11438
|
for (const candidate of candidates) {
|
|
11191
11439
|
try {
|
|
11192
|
-
await
|
|
11440
|
+
await readFile8(candidate, "utf8");
|
|
11193
11441
|
return candidate;
|
|
11194
11442
|
} catch {
|
|
11195
11443
|
}
|
|
@@ -11205,7 +11453,7 @@ async function resolveImportSpecifiers(sourceText, fromDir) {
|
|
|
11205
11453
|
return resolvedPaths;
|
|
11206
11454
|
}
|
|
11207
11455
|
async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateTypeNames = []) {
|
|
11208
|
-
const visited = /* @__PURE__ */ new Set([
|
|
11456
|
+
const visited = /* @__PURE__ */ new Set([resolve9(sourcePath)]);
|
|
11209
11457
|
const discovered = [];
|
|
11210
11458
|
let frontier = [{ text: sourceText, dir: dirname14(sourcePath) }];
|
|
11211
11459
|
for (let hop = 0; hop < MAX_SIBLING_DEPTH && discovered.length < MAX_SIBLING_CANDIDATES_EXPLORED; hop++) {
|
|
@@ -11219,7 +11467,7 @@ async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateType
|
|
|
11219
11467
|
if (discovered.length >= MAX_SIBLING_CANDIDATES_EXPLORED) break;
|
|
11220
11468
|
let content;
|
|
11221
11469
|
try {
|
|
11222
|
-
content = await
|
|
11470
|
+
content = await readFile8(resolvedPath, "utf8");
|
|
11223
11471
|
} catch {
|
|
11224
11472
|
continue;
|
|
11225
11473
|
}
|
|
@@ -11256,7 +11504,7 @@ async function loadComponentSourceRef(name, sourcePath, propNames = [], propType
|
|
|
11256
11504
|
let truncatedSiblingCount = 0;
|
|
11257
11505
|
const usesNotShown = /* @__PURE__ */ new Set();
|
|
11258
11506
|
try {
|
|
11259
|
-
const rawText = await
|
|
11507
|
+
const rawText = await readFile8(sourcePath, "utf8");
|
|
11260
11508
|
let siblingUsesNotShown;
|
|
11261
11509
|
let declaredTypeNames;
|
|
11262
11510
|
({
|
|
@@ -11692,6 +11940,108 @@ function backfillUnclassifiedProps(db, sessionId2) {
|
|
|
11692
11940
|
).run(sessionId2, sessionId2);
|
|
11693
11941
|
return Number(withCategory.changes) + Number(withoutCategory.changes);
|
|
11694
11942
|
}
|
|
11943
|
+
function computeMapTokensInputHash(db, sessionId2, componentSourceRefs = []) {
|
|
11944
|
+
const props = db.prepare(
|
|
11945
|
+
`SELECT rc.name AS component_name, rp.name AS prop_name, rp.cdf_token_kind, rp.default_value
|
|
11946
|
+
FROM raw_props rp
|
|
11947
|
+
JOIN raw_components rc ON rc.session_id = rp.session_id AND rc.component_id = rp.component_id
|
|
11948
|
+
WHERE rp.session_id = ? AND rp.cdf_type = 'token' AND rp.cdf_category = 'design'
|
|
11949
|
+
ORDER BY rc.name, rp.name`
|
|
11950
|
+
).all(sessionId2);
|
|
11951
|
+
const tokens = db.prepare(`SELECT path, type FROM raw_tokens WHERE session_id = ? ORDER BY path`).all(sessionId2);
|
|
11952
|
+
const defaultMappings = db.prepare("SELECT raw_name, path, source FROM raw_token_name_paths WHERE session_id = ? ORDER BY raw_name").all(sessionId2);
|
|
11953
|
+
const payload = {
|
|
11954
|
+
props: props.map((p) => ({
|
|
11955
|
+
component: p.component_name,
|
|
11956
|
+
prop: p.prop_name,
|
|
11957
|
+
tokenKind: p.cdf_token_kind,
|
|
11958
|
+
rawDefault: p.default_value
|
|
11959
|
+
})),
|
|
11960
|
+
tokens,
|
|
11961
|
+
defaultMappings,
|
|
11962
|
+
// The agent's evidence, not just its inputs: a comment or allowlist edit
|
|
11963
|
+
// in a source file (or a sibling it reads) changes the correct answer
|
|
11964
|
+
// without touching props or tokens, so it must invalidate the cache too.
|
|
11965
|
+
sourceRefs: [...componentSourceRefs].sort((a, b) => a.component.localeCompare(b.component)).map((ref) => ({
|
|
11966
|
+
component: ref.component,
|
|
11967
|
+
content: ref.content,
|
|
11968
|
+
siblingFiles: (ref.siblingFiles ?? []).map((s) => ({ path: s.path, content: s.content })).sort((a, b) => a.path.localeCompare(b.path)),
|
|
11969
|
+
usesNotShown: [...ref.usesNotShown ?? []].sort()
|
|
11970
|
+
}))
|
|
11971
|
+
};
|
|
11972
|
+
return createHash5("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
11973
|
+
}
|
|
11974
|
+
function lookupCache(db, inputHash, entityType, entityId, promptHash = "") {
|
|
11975
|
+
const row = db.prepare(
|
|
11976
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11977
|
+
FROM generation_cache
|
|
11978
|
+
WHERE input_hash = ? AND entity_type = ? AND entity_id = ? AND prompt_hash = ?`
|
|
11979
|
+
).get(inputHash, entityType, entityId, promptHash);
|
|
11980
|
+
if (!row) return null;
|
|
11981
|
+
return {
|
|
11982
|
+
inputHash: row.input_hash,
|
|
11983
|
+
entityType: row.entity_type,
|
|
11984
|
+
entityId: row.entity_id,
|
|
11985
|
+
sourceSessionId: row.source_session_id,
|
|
11986
|
+
humanEdited: row.human_edited === 1,
|
|
11987
|
+
promptHash: row.prompt_hash,
|
|
11988
|
+
createdAt: row.created_at,
|
|
11989
|
+
updatedAt: row.updated_at
|
|
11990
|
+
};
|
|
11991
|
+
}
|
|
11992
|
+
function lookupCacheByEntity(db, entityType, entityId) {
|
|
11993
|
+
const row = db.prepare(
|
|
11994
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11995
|
+
FROM generation_cache
|
|
11996
|
+
WHERE entity_type = ? AND entity_id = ?
|
|
11997
|
+
ORDER BY updated_at DESC LIMIT 1`
|
|
11998
|
+
).get(entityType, entityId);
|
|
11999
|
+
if (!row) return null;
|
|
12000
|
+
return {
|
|
12001
|
+
inputHash: row.input_hash,
|
|
12002
|
+
entityType: row.entity_type,
|
|
12003
|
+
entityId: row.entity_id,
|
|
12004
|
+
sourceSessionId: row.source_session_id,
|
|
12005
|
+
humanEdited: row.human_edited === 1,
|
|
12006
|
+
promptHash: row.prompt_hash,
|
|
12007
|
+
createdAt: row.created_at,
|
|
12008
|
+
updatedAt: row.updated_at
|
|
12009
|
+
};
|
|
12010
|
+
}
|
|
12011
|
+
function storeCache(db, inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash = "") {
|
|
12012
|
+
storeCaches(db, [{ inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash }]);
|
|
12013
|
+
}
|
|
12014
|
+
function storeCaches(db, entries) {
|
|
12015
|
+
if (entries.length === 0) return;
|
|
12016
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12017
|
+
const insert = db.prepare(
|
|
12018
|
+
`INSERT INTO generation_cache (input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
12019
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
12020
|
+
ON CONFLICT(input_hash, prompt_hash, entity_type, entity_id) DO UPDATE SET
|
|
12021
|
+
source_session_id = excluded.source_session_id,
|
|
12022
|
+
human_edited = CASE WHEN generation_cache.human_edited = 1 THEN 1 ELSE excluded.human_edited END,
|
|
12023
|
+
updated_at = excluded.updated_at`
|
|
12024
|
+
);
|
|
12025
|
+
db.exec("BEGIN");
|
|
12026
|
+
try {
|
|
12027
|
+
for (const entry of entries) {
|
|
12028
|
+
insert.run(
|
|
12029
|
+
entry.inputHash,
|
|
12030
|
+
entry.entityType,
|
|
12031
|
+
entry.entityId,
|
|
12032
|
+
entry.sourceSessionId,
|
|
12033
|
+
entry.humanEdited ? 1 : 0,
|
|
12034
|
+
now,
|
|
12035
|
+
now,
|
|
12036
|
+
entry.promptHash ?? ""
|
|
12037
|
+
);
|
|
12038
|
+
}
|
|
12039
|
+
db.exec("COMMIT");
|
|
12040
|
+
} catch (e) {
|
|
12041
|
+
db.exec("ROLLBACK");
|
|
12042
|
+
throw e;
|
|
12043
|
+
}
|
|
12044
|
+
}
|
|
11695
12045
|
function storeScannedFiles(db, sessionId2, filePaths) {
|
|
11696
12046
|
db.exec("BEGIN");
|
|
11697
12047
|
try {
|
|
@@ -11774,7 +12124,105 @@ function filterUnknownSlotAllowedComponents(db, sessionId2, allowedComponentName
|
|
|
11774
12124
|
}
|
|
11775
12125
|
return unknown;
|
|
11776
12126
|
}
|
|
11777
|
-
function
|
|
12127
|
+
function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentId, manageTransaction = true, options = {}) {
|
|
12128
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12129
|
+
if (manageTransaction) db.exec("BEGIN");
|
|
12130
|
+
try {
|
|
12131
|
+
const srcComp = db.prepare(
|
|
12132
|
+
`SELECT description, status, component_description_rationale, props_rationale, slots_rationale
|
|
12133
|
+
FROM raw_components WHERE session_id = ? AND component_id = ?`
|
|
12134
|
+
).get(sourceSessionId, componentId);
|
|
12135
|
+
if (srcComp) {
|
|
12136
|
+
db.prepare(
|
|
12137
|
+
`UPDATE raw_components
|
|
12138
|
+
SET description = ?, status = ?, component_description_rationale = ?, props_rationale = ?, slots_rationale = ?, extracted_at = ?
|
|
12139
|
+
WHERE session_id = ? AND component_id = ?`
|
|
12140
|
+
).run(
|
|
12141
|
+
srcComp.description,
|
|
12142
|
+
srcComp.status,
|
|
12143
|
+
srcComp.component_description_rationale,
|
|
12144
|
+
srcComp.props_rationale,
|
|
12145
|
+
srcComp.slots_rationale,
|
|
12146
|
+
now,
|
|
12147
|
+
targetSessionId,
|
|
12148
|
+
componentId
|
|
12149
|
+
);
|
|
12150
|
+
}
|
|
12151
|
+
const srcProps = db.prepare(
|
|
12152
|
+
`SELECT name, cdf_type, cdf_category, cdf_token_kind, required, description, default_value, rationale
|
|
12153
|
+
FROM raw_props WHERE session_id = ? AND component_id = ?`
|
|
12154
|
+
).all(sourceSessionId, componentId);
|
|
12155
|
+
for (const p of srcProps) {
|
|
12156
|
+
db.prepare(
|
|
12157
|
+
`UPDATE raw_props SET cdf_type = ?, cdf_category = ?, cdf_token_kind = ?, required = ?, description = ?, default_value = ?, rationale = ?
|
|
12158
|
+
WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12159
|
+
).run(
|
|
12160
|
+
p.cdf_type,
|
|
12161
|
+
p.cdf_category,
|
|
12162
|
+
p.cdf_token_kind,
|
|
12163
|
+
p.required,
|
|
12164
|
+
p.description,
|
|
12165
|
+
p.default_value,
|
|
12166
|
+
p.rationale,
|
|
12167
|
+
targetSessionId,
|
|
12168
|
+
componentId,
|
|
12169
|
+
p.name
|
|
12170
|
+
);
|
|
12171
|
+
}
|
|
12172
|
+
db.prepare(`DELETE FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`).run(
|
|
12173
|
+
targetSessionId,
|
|
12174
|
+
componentId
|
|
12175
|
+
);
|
|
12176
|
+
const srcAV = db.prepare(
|
|
12177
|
+
`SELECT prop_name, position, value FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`
|
|
12178
|
+
).all(sourceSessionId, componentId);
|
|
12179
|
+
const insertAV = db.prepare(
|
|
12180
|
+
`INSERT INTO raw_prop_allowed_values (session_id, component_id, prop_name, position, value) VALUES (?, ?, ?, ?, ?)`
|
|
12181
|
+
);
|
|
12182
|
+
for (const av of srcAV) {
|
|
12183
|
+
insertAV.run(targetSessionId, componentId, av.prop_name, av.position, av.value);
|
|
12184
|
+
}
|
|
12185
|
+
const srcSlots = db.prepare(`SELECT name, required, description, rationale FROM raw_slots WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
|
|
12186
|
+
for (const s of srcSlots) {
|
|
12187
|
+
db.prepare(
|
|
12188
|
+
`UPDATE raw_slots SET required = ?, description = ?, rationale = ? WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12189
|
+
).run(s.required, s.description, s.rationale, targetSessionId, componentId, s.name);
|
|
12190
|
+
}
|
|
12191
|
+
db.prepare(`DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`).run(
|
|
12192
|
+
targetSessionId,
|
|
12193
|
+
componentId
|
|
12194
|
+
);
|
|
12195
|
+
const srcSAC = db.prepare(
|
|
12196
|
+
`SELECT slot_name, position, allowed_component FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`
|
|
12197
|
+
).all(sourceSessionId, componentId);
|
|
12198
|
+
const insertSAC = db.prepare(
|
|
12199
|
+
`INSERT INTO raw_slot_allowed_components (session_id, component_id, slot_name, allowed_component, position) VALUES (?, ?, ?, ?, ?)`
|
|
12200
|
+
);
|
|
12201
|
+
const allowedSAC = options.allowedComponentNames ? srcSAC.filter((sac) => options.allowedComponentNames.has(sac.allowed_component)) : srcSAC;
|
|
12202
|
+
for (const sac of allowedSAC) {
|
|
12203
|
+
insertSAC.run(targetSessionId, componentId, sac.slot_name, sac.allowed_component, sac.position);
|
|
12204
|
+
}
|
|
12205
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12206
|
+
if (manageTransaction) db.exec("COMMIT");
|
|
12207
|
+
} catch (e) {
|
|
12208
|
+
if (manageTransaction) db.exec("ROLLBACK");
|
|
12209
|
+
throw e;
|
|
12210
|
+
}
|
|
12211
|
+
}
|
|
12212
|
+
function copyComponentsFromCache(db, entries, options = {}) {
|
|
12213
|
+
if (entries.length === 0) return;
|
|
12214
|
+
db.exec("BEGIN");
|
|
12215
|
+
try {
|
|
12216
|
+
for (const entry of entries) {
|
|
12217
|
+
copyComponentFromCache(db, entry.sourceSessionId, entry.targetSessionId, entry.componentId, false, options);
|
|
12218
|
+
}
|
|
12219
|
+
db.exec("COMMIT");
|
|
12220
|
+
} catch (e) {
|
|
12221
|
+
db.exec("ROLLBACK");
|
|
12222
|
+
throw e;
|
|
12223
|
+
}
|
|
12224
|
+
}
|
|
12225
|
+
function copyTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
11778
12226
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11779
12227
|
db.exec("BEGIN");
|
|
11780
12228
|
try {
|
|
@@ -11795,7 +12243,153 @@ function copyTokensBetweenSessions(db, sourceSessionId, targetSessionId) {
|
|
|
11795
12243
|
throw e;
|
|
11796
12244
|
}
|
|
11797
12245
|
}
|
|
11798
|
-
|
|
12246
|
+
function copyMapTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
12247
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12248
|
+
let copiedCount = 0;
|
|
12249
|
+
db.exec("BEGIN");
|
|
12250
|
+
try {
|
|
12251
|
+
const sourceRows = db.prepare(
|
|
12252
|
+
`SELECT rc.name AS component_name, rptp.prop_name, rptp.source, rptp.position, rptp.path
|
|
12253
|
+
FROM raw_prop_token_paths rptp
|
|
12254
|
+
JOIN raw_components rc ON rc.session_id = rptp.session_id AND rc.component_id = rptp.component_id
|
|
12255
|
+
WHERE rptp.session_id = ?
|
|
12256
|
+
ORDER BY rc.name, rptp.prop_name, rptp.position`
|
|
12257
|
+
).all(sourceSessionId);
|
|
12258
|
+
const targetComponents = db.prepare(`SELECT component_id, name FROM raw_components WHERE session_id = ?`).all(targetSessionId);
|
|
12259
|
+
const targetIdByName = new Map(targetComponents.map((c2) => [c2.name, c2.component_id]));
|
|
12260
|
+
const targetProps = new Set(
|
|
12261
|
+
db.prepare(`SELECT component_id, name FROM raw_props WHERE session_id = ?`).all(targetSessionId).map((p) => `${p.component_id}::${p.name}`)
|
|
12262
|
+
);
|
|
12263
|
+
const insertPath = db.prepare(
|
|
12264
|
+
`INSERT INTO raw_prop_token_paths (session_id, component_id, prop_name, source, position, path)
|
|
12265
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
12266
|
+
);
|
|
12267
|
+
const clearedProps = /* @__PURE__ */ new Set();
|
|
12268
|
+
const copiedProps = /* @__PURE__ */ new Set();
|
|
12269
|
+
for (const row of sourceRows) {
|
|
12270
|
+
const targetComponentId = targetIdByName.get(row.component_name);
|
|
12271
|
+
if (!targetComponentId) continue;
|
|
12272
|
+
if (!targetProps.has(`${targetComponentId}::${row.prop_name}`)) continue;
|
|
12273
|
+
const propKey = `${targetComponentId}::${row.prop_name}`;
|
|
12274
|
+
if (!clearedProps.has(propKey)) {
|
|
12275
|
+
clearedProps.add(propKey);
|
|
12276
|
+
db.prepare(`DELETE FROM raw_prop_token_paths WHERE session_id = ? AND component_id = ? AND prop_name = ?`).run(
|
|
12277
|
+
targetSessionId,
|
|
12278
|
+
targetComponentId,
|
|
12279
|
+
row.prop_name
|
|
12280
|
+
);
|
|
12281
|
+
}
|
|
12282
|
+
insertPath.run(targetSessionId, targetComponentId, row.prop_name, row.source, row.position, row.path);
|
|
12283
|
+
copiedProps.add(propKey);
|
|
12284
|
+
}
|
|
12285
|
+
copiedCount = copiedProps.size;
|
|
12286
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12287
|
+
db.exec("COMMIT");
|
|
12288
|
+
} catch (e) {
|
|
12289
|
+
db.exec("ROLLBACK");
|
|
12290
|
+
throw e;
|
|
12291
|
+
}
|
|
12292
|
+
return copiedCount;
|
|
12293
|
+
}
|
|
12294
|
+
async function getCliCacheVersion() {
|
|
12295
|
+
if (_cliCacheVersionCache) return _cliCacheVersionCache;
|
|
12296
|
+
try {
|
|
12297
|
+
const { hashContent: hashContent2 } = await Promise.resolve().then(() => (init_cache_keys(), cache_keys_exports));
|
|
12298
|
+
const { resolveSkillPath: resolveSkillPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
12299
|
+
const skills = ["components", "tokens", "select"];
|
|
12300
|
+
const parts = [];
|
|
12301
|
+
for (const s of skills) {
|
|
12302
|
+
try {
|
|
12303
|
+
const p = resolveSkillPath2(s);
|
|
12304
|
+
parts.push(readFileSync5(p, "utf8"));
|
|
12305
|
+
} catch {
|
|
12306
|
+
parts.push(`<missing:${s}>`);
|
|
12307
|
+
}
|
|
12308
|
+
}
|
|
12309
|
+
_cliCacheVersionCache = hashContent2(parts.join("\n---\n"));
|
|
12310
|
+
return _cliCacheVersionCache;
|
|
12311
|
+
} catch {
|
|
12312
|
+
_cliCacheVersionCache = "fallback";
|
|
12313
|
+
return _cliCacheVersionCache;
|
|
12314
|
+
}
|
|
12315
|
+
}
|
|
12316
|
+
function storeExtractCache(db, filePath, fileHash, cliVersion2, components) {
|
|
12317
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12318
|
+
const componentsJson = JSON.stringify(components);
|
|
12319
|
+
db.prepare(
|
|
12320
|
+
`INSERT INTO extract_cache (file_path, file_hash, cli_version, created_at, updated_at, components_json)
|
|
12321
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
12322
|
+
ON CONFLICT(file_hash, cli_version) DO UPDATE SET
|
|
12323
|
+
file_path = excluded.file_path,
|
|
12324
|
+
updated_at = excluded.updated_at,
|
|
12325
|
+
components_json = excluded.components_json`
|
|
12326
|
+
).run(filePath, fileHash, cliVersion2, now, now, componentsJson);
|
|
12327
|
+
}
|
|
12328
|
+
function lookupExtractCache(db, fileHash, cliVersion2) {
|
|
12329
|
+
const row = db.prepare(
|
|
12330
|
+
`SELECT file_path, file_hash, cli_version, created_at, updated_at, components_json
|
|
12331
|
+
FROM extract_cache
|
|
12332
|
+
WHERE file_hash = ? AND cli_version = ?`
|
|
12333
|
+
).get(fileHash, cliVersion2);
|
|
12334
|
+
if (!row) return null;
|
|
12335
|
+
let components = [];
|
|
12336
|
+
try {
|
|
12337
|
+
components = JSON.parse(row.components_json);
|
|
12338
|
+
} catch {
|
|
12339
|
+
return null;
|
|
12340
|
+
}
|
|
12341
|
+
return {
|
|
12342
|
+
filePath: row.file_path,
|
|
12343
|
+
fileHash: row.file_hash,
|
|
12344
|
+
cliVersion: row.cli_version,
|
|
12345
|
+
createdAt: row.created_at,
|
|
12346
|
+
updatedAt: row.updated_at,
|
|
12347
|
+
components
|
|
12348
|
+
};
|
|
12349
|
+
}
|
|
12350
|
+
function storeCompositionCache(db, inputHash, cliVersion2, agentOutput) {
|
|
12351
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12352
|
+
db.prepare(
|
|
12353
|
+
`INSERT INTO composition_cache (input_hash, cli_version, agent_output, created_at, updated_at)
|
|
12354
|
+
VALUES (?, ?, ?, ?, ?)
|
|
12355
|
+
ON CONFLICT(input_hash, cli_version) DO UPDATE SET
|
|
12356
|
+
agent_output = excluded.agent_output,
|
|
12357
|
+
updated_at = excluded.updated_at`
|
|
12358
|
+
).run(inputHash, cliVersion2, agentOutput, now, now);
|
|
12359
|
+
}
|
|
12360
|
+
function lookupCompositionCache(db, inputHash, cliVersion2) {
|
|
12361
|
+
const row = db.prepare(`SELECT agent_output FROM composition_cache WHERE input_hash = ? AND cli_version = ?`).get(inputHash, cliVersion2);
|
|
12362
|
+
return row ? row.agent_output : null;
|
|
12363
|
+
}
|
|
12364
|
+
function storeSelectCache(db, componentHash, promptHash, cliVersion2, decision, reason) {
|
|
12365
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12366
|
+
db.prepare(
|
|
12367
|
+
`INSERT INTO select_cache (component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at)
|
|
12368
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
12369
|
+
ON CONFLICT(component_hash, prompt_hash, cli_version) DO UPDATE SET
|
|
12370
|
+
decision = excluded.decision,
|
|
12371
|
+
reason = excluded.reason,
|
|
12372
|
+
updated_at = excluded.updated_at`
|
|
12373
|
+
).run(componentHash, promptHash, cliVersion2, decision, reason, now, now);
|
|
12374
|
+
}
|
|
12375
|
+
function lookupSelectCache(db, componentHash, promptHash, cliVersion2) {
|
|
12376
|
+
const row = db.prepare(
|
|
12377
|
+
`SELECT component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at
|
|
12378
|
+
FROM select_cache
|
|
12379
|
+
WHERE component_hash = ? AND prompt_hash = ? AND cli_version = ?`
|
|
12380
|
+
).get(componentHash, promptHash, cliVersion2);
|
|
12381
|
+
if (!row) return null;
|
|
12382
|
+
return {
|
|
12383
|
+
componentHash: row.component_hash,
|
|
12384
|
+
promptHash: row.prompt_hash,
|
|
12385
|
+
cliVersion: row.cli_version,
|
|
12386
|
+
decision: row.decision,
|
|
12387
|
+
reason: row.reason,
|
|
12388
|
+
createdAt: row.created_at,
|
|
12389
|
+
updatedAt: row.updated_at
|
|
12390
|
+
};
|
|
12391
|
+
}
|
|
12392
|
+
var SCHEMA, MAX_COMPONENT_SOURCE_CHARS, MAX_SIBLING_FILES, MAX_SIBLING_SNIPPET_CHARS, MAX_TYPE_DECLARING_SIBLING_CHARS, MAX_ENLARGED_SIBLINGS, MAX_SIBLING_DEPTH, MAX_SIBLING_CANDIDATES_EXPLORED, RELATIVE_IMPORT_PATTERN, SIBLING_FILE_EXTENSIONS, TS_ESM_EXTENSION_REWRITES, IDENTIFIER_PATTERN, _cliCacheVersionCache;
|
|
11799
12393
|
var init_db = __esm({
|
|
11800
12394
|
"packages/experience-design-system-cli-legacy/src/session/db.ts"() {
|
|
11801
12395
|
"use strict";
|
|
@@ -11809,6 +12403,8 @@ var init_db = __esm({
|
|
|
11809
12403
|
init_write2();
|
|
11810
12404
|
init_session_resolver();
|
|
11811
12405
|
init_read3();
|
|
12406
|
+
init_hash_component_shape();
|
|
12407
|
+
init_hash_token_content();
|
|
11812
12408
|
init_read3();
|
|
11813
12409
|
init_store_dtcg_tokens();
|
|
11814
12410
|
init_apply_tool_calls();
|
|
@@ -11932,6 +12528,17 @@ CREATE TABLE IF NOT EXISTS raw_tokens (
|
|
|
11932
12528
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
11933
12529
|
);
|
|
11934
12530
|
|
|
12531
|
+
CREATE TABLE IF NOT EXISTS generation_cache (
|
|
12532
|
+
input_hash TEXT NOT NULL,
|
|
12533
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
12534
|
+
entity_id TEXT NOT NULL,
|
|
12535
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
12536
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
12537
|
+
created_at TEXT NOT NULL,
|
|
12538
|
+
updated_at TEXT NOT NULL,
|
|
12539
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
12540
|
+
);
|
|
12541
|
+
|
|
11935
12542
|
CREATE TABLE IF NOT EXISTS scanned_files (
|
|
11936
12543
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
11937
12544
|
path TEXT NOT NULL,
|
|
@@ -11977,9 +12584,10 @@ CREATE INDEX IF NOT EXISTS idx_raw_props_session ON raw_props(session_id,
|
|
|
11977
12584
|
CREATE INDEX IF NOT EXISTS idx_raw_slots_session ON raw_slots(session_id, component_id);
|
|
11978
12585
|
CREATE INDEX IF NOT EXISTS idx_raw_tokens_session ON raw_tokens(session_id);
|
|
11979
12586
|
CREATE INDEX IF NOT EXISTS idx_raw_token_groups_session ON raw_token_groups(session_id);
|
|
12587
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
12588
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
11980
12589
|
CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session_id);
|
|
11981
12590
|
`;
|
|
11982
|
-
REMOVED_CACHE_TABLES = ["generation_cache", "extract_cache", "composition_cache", "select_cache"];
|
|
11983
12591
|
MAX_COMPONENT_SOURCE_CHARS = 8e3;
|
|
11984
12592
|
MAX_SIBLING_FILES = 5;
|
|
11985
12593
|
MAX_SIBLING_SNIPPET_CHARS = 1200;
|
|
@@ -11996,15 +12604,16 @@ CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session
|
|
|
11996
12604
|
[".cjs", [".cts", ".cjs"]]
|
|
11997
12605
|
];
|
|
11998
12606
|
IDENTIFIER_PATTERN = /[A-Za-z_$][A-Za-z0-9_$]*/g;
|
|
12607
|
+
_cliCacheVersionCache = null;
|
|
11999
12608
|
}
|
|
12000
12609
|
});
|
|
12001
12610
|
|
|
12002
12611
|
// packages/experience-design-system-cli-legacy/src/helpers/read-existing-contentful-entities-from-session.ts
|
|
12003
|
-
import { readFile as
|
|
12612
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
12004
12613
|
async function readExistingContentfulEntitiesFromSession(path) {
|
|
12005
12614
|
if (!path) return void 0;
|
|
12006
12615
|
try {
|
|
12007
|
-
const raw = await
|
|
12616
|
+
const raw = await readFile9(path, "utf8");
|
|
12008
12617
|
const parsed = JSON.parse(raw);
|
|
12009
12618
|
if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens)) return void 0;
|
|
12010
12619
|
return parsed;
|
|
@@ -12128,21 +12737,21 @@ var init_resolve_session_id = __esm({
|
|
|
12128
12737
|
});
|
|
12129
12738
|
|
|
12130
12739
|
// packages/experience-design-system-cli-legacy/src/analyze/select/persistence.ts
|
|
12131
|
-
import { access, appendFile, mkdir as mkdir2, readFile as
|
|
12740
|
+
import { access, appendFile, mkdir as mkdir2, readFile as readFile10, writeFile as writeFile2 } from "node:fs/promises";
|
|
12132
12741
|
import { homedir as homedir4 } from "node:os";
|
|
12133
|
-
import { resolve as
|
|
12742
|
+
import { resolve as resolve10 } from "node:path";
|
|
12134
12743
|
function getRefineArtifactsRoot() {
|
|
12135
12744
|
if (process.env.EDS_REVIEW_ARTIFACTS_DIR) {
|
|
12136
|
-
return
|
|
12745
|
+
return resolve10(process.env.EDS_REVIEW_ARTIFACTS_DIR);
|
|
12137
12746
|
}
|
|
12138
|
-
return
|
|
12747
|
+
return resolve10(homedir4(), ".contentful", "experience-design-system-cli", "reviews");
|
|
12139
12748
|
}
|
|
12140
12749
|
async function getRefineSessionPaths(sessionId2, artifactsRoot) {
|
|
12141
|
-
const sessionDir =
|
|
12750
|
+
const sessionDir = resolve10(artifactsRoot, sessionId2);
|
|
12142
12751
|
return {
|
|
12143
12752
|
sessionDir,
|
|
12144
|
-
eventsPath:
|
|
12145
|
-
statePath:
|
|
12753
|
+
eventsPath: resolve10(sessionDir, "events.jsonl"),
|
|
12754
|
+
statePath: resolve10(sessionDir, "current-review-state.json")
|
|
12146
12755
|
};
|
|
12147
12756
|
}
|
|
12148
12757
|
async function saveReviewState(statePath, session) {
|
|
@@ -12153,7 +12762,7 @@ async function ensureRefineSession(sessionId2, artifactsRoot, initialSnapshot) {
|
|
|
12153
12762
|
await mkdir2(paths.sessionDir, { recursive: true });
|
|
12154
12763
|
try {
|
|
12155
12764
|
await access(paths.statePath);
|
|
12156
|
-
const savedState = await
|
|
12765
|
+
const savedState = await readFile10(paths.statePath, "utf8");
|
|
12157
12766
|
return JSON.parse(savedState);
|
|
12158
12767
|
} catch {
|
|
12159
12768
|
await writeFile2(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
|
|
@@ -12638,8 +13247,8 @@ var init_path_exists = __esm({
|
|
|
12638
13247
|
});
|
|
12639
13248
|
|
|
12640
13249
|
// packages/experience-design-system-cli-legacy/src/lib/prompt-overrides.ts
|
|
12641
|
-
import { readFile as
|
|
12642
|
-
import { resolve as
|
|
13250
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
13251
|
+
import { resolve as resolve11 } from "node:path";
|
|
12643
13252
|
function looksLikePath(value) {
|
|
12644
13253
|
if (value.includes("/") || value.includes("\\")) return true;
|
|
12645
13254
|
if (value.startsWith("~")) return true;
|
|
@@ -12671,9 +13280,9 @@ function parsePromptOverrides(inputs) {
|
|
|
12671
13280
|
}
|
|
12672
13281
|
async function resolvePromptOverride(override) {
|
|
12673
13282
|
if (override.kind === "text") return override.value;
|
|
12674
|
-
const abs =
|
|
13283
|
+
const abs = resolve11(override.value);
|
|
12675
13284
|
try {
|
|
12676
|
-
return await
|
|
13285
|
+
return await readFile11(abs, "utf8");
|
|
12677
13286
|
} catch {
|
|
12678
13287
|
throw new Error(`--prompt: could not read prompt file: ${abs}`);
|
|
12679
13288
|
}
|
|
@@ -12688,21 +13297,21 @@ var init_prompt_overrides = __esm({
|
|
|
12688
13297
|
|
|
12689
13298
|
// packages/experience-design-system-cli-legacy/src/generate/command.ts
|
|
12690
13299
|
import { createElement } from "react";
|
|
12691
|
-
import { readFile as
|
|
12692
|
-
import { join as join14, resolve as
|
|
13300
|
+
import { readFile as readFile12, readdir, stat } from "node:fs/promises";
|
|
13301
|
+
import { join as join14, resolve as resolve12 } from "node:path";
|
|
12693
13302
|
async function assertFileExists(flag, p) {
|
|
12694
13303
|
if (!await pathExists(p)) die(`Error: file not found: ${p} (from ${flag})`);
|
|
12695
13304
|
}
|
|
12696
13305
|
async function readFileInline(path) {
|
|
12697
13306
|
if (!path) return void 0;
|
|
12698
|
-
const resolved =
|
|
13307
|
+
const resolved = resolve12(path);
|
|
12699
13308
|
let s;
|
|
12700
13309
|
try {
|
|
12701
13310
|
s = await stat(resolved);
|
|
12702
13311
|
} catch {
|
|
12703
13312
|
return void 0;
|
|
12704
13313
|
}
|
|
12705
|
-
if (!s.isDirectory()) return
|
|
13314
|
+
if (!s.isDirectory()) return readFile12(resolved, "utf8");
|
|
12706
13315
|
const files = [];
|
|
12707
13316
|
async function walk(dir) {
|
|
12708
13317
|
let entries;
|
|
@@ -12728,7 +13337,7 @@ async function readFileInline(path) {
|
|
|
12728
13337
|
}
|
|
12729
13338
|
await walk(resolved);
|
|
12730
13339
|
if (files.length === 0) return void 0;
|
|
12731
|
-
const parts = await Promise.all(files.map((f) =>
|
|
13340
|
+
const parts = await Promise.all(files.map((f) => readFile12(f, "utf8").catch(() => "")));
|
|
12732
13341
|
return parts.filter(Boolean).join("\n\n");
|
|
12733
13342
|
}
|
|
12734
13343
|
function printFallbackInstructions(options) {
|
|
@@ -12753,6 +13362,23 @@ function printFallbackInstructions(options) {
|
|
|
12753
13362
|
function generatePropBuckets(component) {
|
|
12754
13363
|
return logPropBuckets("generate", [bucketComponentProps(component)]);
|
|
12755
13364
|
}
|
|
13365
|
+
function createCachedComponentResult(componentName, warnings = []) {
|
|
13366
|
+
return {
|
|
13367
|
+
componentName,
|
|
13368
|
+
classified: 0,
|
|
13369
|
+
excluded: 0,
|
|
13370
|
+
slots: 0,
|
|
13371
|
+
warnings,
|
|
13372
|
+
failed: false,
|
|
13373
|
+
cached: true,
|
|
13374
|
+
renamedSlotsCount: 0
|
|
13375
|
+
};
|
|
13376
|
+
}
|
|
13377
|
+
function writeCachedComponentStatus(position, componentName, pinned) {
|
|
13378
|
+
const status = pinned ? c.cyan("pinned (human-edited)") : c.green("cached");
|
|
13379
|
+
process.stderr.write(` ${position} ${c.bold(componentName)} ${status}
|
|
13380
|
+
`);
|
|
13381
|
+
}
|
|
12756
13382
|
async function showGenerateView(result) {
|
|
12757
13383
|
if (process.stdout.isTTY) {
|
|
12758
13384
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -12773,6 +13399,29 @@ session=${result.sessionId}
|
|
|
12773
13399
|
);
|
|
12774
13400
|
await exitWithAnalytics(0);
|
|
12775
13401
|
}
|
|
13402
|
+
function normalizeComponentForCache(component) {
|
|
13403
|
+
const slots = component.slots.map((slot, index, allSlots) => ({
|
|
13404
|
+
...slot,
|
|
13405
|
+
name: slot.name.trim() || (allSlots.length === 1 ? "children" : `slot_${index}`)
|
|
13406
|
+
}));
|
|
13407
|
+
return { ...component, slots };
|
|
13408
|
+
}
|
|
13409
|
+
function lookupComponentCache(db, component, promptHash) {
|
|
13410
|
+
const normalized = normalizeComponentForCache(component);
|
|
13411
|
+
const inputHash = hashComponentShape(normalized);
|
|
13412
|
+
const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
|
|
13413
|
+
if (cached) return cached;
|
|
13414
|
+
const legacyInputHash = hashComponentShape(component);
|
|
13415
|
+
return legacyInputHash === inputHash ? null : lookupCache(db, legacyInputHash, "component", component.component_id, promptHash);
|
|
13416
|
+
}
|
|
13417
|
+
function resolveComponentCache(db, component, promptHash, allowedComponentNames2) {
|
|
13418
|
+
const cached = lookupComponentCache(db, component, promptHash);
|
|
13419
|
+
if (cached && findUnknownSlotAllowedComponents(db, cached.sourceSessionId, allowedComponentNames2, component.component_id).length === 0) {
|
|
13420
|
+
return { entry: cached, humanEdited: cached.humanEdited };
|
|
13421
|
+
}
|
|
13422
|
+
const pinned = lookupCacheByEntity(db, "component", component.component_id);
|
|
13423
|
+
return pinned?.humanEdited && findUnknownSlotAllowedComponents(db, pinned.sourceSessionId, allowedComponentNames2, component.component_id).length === 0 ? { entry: pinned, humanEdited: true } : null;
|
|
13424
|
+
}
|
|
12776
13425
|
async function runOneComponent(options, component, index, total) {
|
|
12777
13426
|
const {
|
|
12778
13427
|
agent,
|
|
@@ -12782,10 +13431,13 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12782
13431
|
tokensInline,
|
|
12783
13432
|
tokenMapInline,
|
|
12784
13433
|
verbose,
|
|
13434
|
+
noCache,
|
|
12785
13435
|
skillPathOverride,
|
|
12786
13436
|
skillContentOverride,
|
|
13437
|
+
promptHash,
|
|
12787
13438
|
existingContentfulEntities,
|
|
12788
13439
|
existingTokensInline,
|
|
13440
|
+
precomputedCachedNames,
|
|
12789
13441
|
allowedComponentNames: allowedComponentNames2
|
|
12790
13442
|
} = options;
|
|
12791
13443
|
const pos = c.dim(`[${index + 1}/${total}]`);
|
|
@@ -12810,6 +13462,40 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12810
13462
|
allowedComponents: slot.allowedComponents.filter((name) => allowedComponentNames2.has(name))
|
|
12811
13463
|
};
|
|
12812
13464
|
});
|
|
13465
|
+
const cacheComponent = normalizeComponentForCache(component);
|
|
13466
|
+
if (!noCache && precomputedCachedNames.has(component.name)) {
|
|
13467
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13468
|
+
return createCachedComponentResult(component.name);
|
|
13469
|
+
}
|
|
13470
|
+
if (!noCache) {
|
|
13471
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13472
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13473
|
+
if (resolution && !resolution.humanEdited) {
|
|
13474
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13475
|
+
allowedComponentNames: allowedComponentNames2
|
|
13476
|
+
});
|
|
13477
|
+
storeCache(
|
|
13478
|
+
db,
|
|
13479
|
+
inputHash,
|
|
13480
|
+
"component",
|
|
13481
|
+
component.component_id,
|
|
13482
|
+
resolution.entry.sourceSessionId,
|
|
13483
|
+
resolution.entry.humanEdited,
|
|
13484
|
+
promptHash
|
|
13485
|
+
);
|
|
13486
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13487
|
+
return createCachedComponentResult(component.name);
|
|
13488
|
+
}
|
|
13489
|
+
if (resolution?.humanEdited) {
|
|
13490
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13491
|
+
allowedComponentNames: allowedComponentNames2
|
|
13492
|
+
});
|
|
13493
|
+
writeCachedComponentStatus(pos, component.name, true);
|
|
13494
|
+
return createCachedComponentResult(`${component.name}`, [
|
|
13495
|
+
`${component.name}: source changed but human edits preserved`
|
|
13496
|
+
]);
|
|
13497
|
+
}
|
|
13498
|
+
}
|
|
12813
13499
|
const rawComponentsInline = JSON.stringify(
|
|
12814
13500
|
[
|
|
12815
13501
|
{
|
|
@@ -12882,6 +13568,10 @@ ${outputBuf}`);
|
|
|
12882
13568
|
const applied = applyToolCalls(db, sessionId2, component.component_id, component.name, calls, warnings, {
|
|
12883
13569
|
allowedComponentNames: allowedComponentNames2
|
|
12884
13570
|
});
|
|
13571
|
+
if (!noCache) {
|
|
13572
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13573
|
+
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
13574
|
+
}
|
|
12885
13575
|
return {
|
|
12886
13576
|
componentName: component.name,
|
|
12887
13577
|
classified: applied.classified,
|
|
@@ -12933,7 +13623,7 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12933
13623
|
try {
|
|
12934
13624
|
const artifactsRoot = getRefineArtifactsRoot();
|
|
12935
13625
|
const paths = await getRefineSessionPaths(sessionId2, artifactsRoot);
|
|
12936
|
-
const raw = await
|
|
13626
|
+
const raw = await readFile12(paths.statePath, "utf8");
|
|
12937
13627
|
const snapshot = JSON.parse(raw);
|
|
12938
13628
|
const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
|
|
12939
13629
|
if (accepted.length === 0) return null;
|
|
@@ -12942,6 +13632,15 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12942
13632
|
return null;
|
|
12943
13633
|
}
|
|
12944
13634
|
}
|
|
13635
|
+
function parsePrecomputedCachedNames(value) {
|
|
13636
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
13637
|
+
try {
|
|
13638
|
+
const parsed = JSON.parse(value);
|
|
13639
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((name) => typeof name === "string") : []);
|
|
13640
|
+
} catch {
|
|
13641
|
+
return /* @__PURE__ */ new Set();
|
|
13642
|
+
}
|
|
13643
|
+
}
|
|
12945
13644
|
async function runGenerateSkill(skill, opts, verbose = false) {
|
|
12946
13645
|
const savedCreds = await readExperiencesCredentials();
|
|
12947
13646
|
const agentName = opts.agent ?? savedCreds.agent;
|
|
@@ -12970,8 +13669,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12970
13669
|
}
|
|
12971
13670
|
const generatePromptPath = generatePrompt === void 0 ? configuredGeneratePromptPath : void 0;
|
|
12972
13671
|
if (generatePromptPath) {
|
|
12973
|
-
if (!await pathExists(
|
|
12974
|
-
die(`Error: custom prompt path not found: ${
|
|
13672
|
+
if (!await pathExists(resolve12(generatePromptPath))) {
|
|
13673
|
+
die(`Error: custom prompt path not found: ${resolve12(generatePromptPath)}`);
|
|
12975
13674
|
}
|
|
12976
13675
|
if (!generatePromptPath.toLowerCase().endsWith(".md")) {
|
|
12977
13676
|
process.stderr.write(
|
|
@@ -12979,7 +13678,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12979
13678
|
`
|
|
12980
13679
|
);
|
|
12981
13680
|
}
|
|
12982
|
-
process.stderr.write(formatCustomPromptBanner("components",
|
|
13681
|
+
process.stderr.write(formatCustomPromptBanner("components", resolve12(generatePromptPath)));
|
|
12983
13682
|
}
|
|
12984
13683
|
if (skill === "tokens" && !opts.rawTokens) {
|
|
12985
13684
|
die("Error: --raw-tokens is required when using generate tokens");
|
|
@@ -12995,7 +13694,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12995
13694
|
let existingContentfulEntities;
|
|
12996
13695
|
let existingTokensInline;
|
|
12997
13696
|
if (opts.existingEntitiesPath) {
|
|
12998
|
-
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
13697
|
+
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(resolve12(opts.existingEntitiesPath));
|
|
12999
13698
|
if (existingContentfulEntities) {
|
|
13000
13699
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
13001
13700
|
} else {
|
|
@@ -13094,7 +13793,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13094
13793
|
rawComponentsInline: sampleInline ?? rawTokensInline,
|
|
13095
13794
|
propBucketsInline: sampleComponent ? generatePropBuckets(sampleComponent) : void 0,
|
|
13096
13795
|
rawTokensInline: skill === "tokens" ? rawTokensInline : void 0,
|
|
13097
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13796
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13098
13797
|
tokensInline,
|
|
13099
13798
|
tokenMapInline,
|
|
13100
13799
|
outDir: process.cwd(),
|
|
@@ -13120,7 +13819,64 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13120
13819
|
if (skill === "components" && allComponents && sessionId2) {
|
|
13121
13820
|
const db = openPipelineDb();
|
|
13122
13821
|
let componentResults;
|
|
13822
|
+
const precomputedCachedNames = parsePrecomputedCachedNames(opts.cachedComponents);
|
|
13123
13823
|
try {
|
|
13824
|
+
const existingContentfulEntitiesHashInputs = [];
|
|
13825
|
+
if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
|
|
13826
|
+
const promptHash = await hashPromptForSkill(
|
|
13827
|
+
"components",
|
|
13828
|
+
agent,
|
|
13829
|
+
model,
|
|
13830
|
+
generatePromptPath,
|
|
13831
|
+
existingContentfulEntitiesHashInputs,
|
|
13832
|
+
generatePrompt
|
|
13833
|
+
);
|
|
13834
|
+
if (opts.cacheStatus) {
|
|
13835
|
+
const cacheEnabled = opts.cache !== false && process.env.EDS_NO_CACHE !== "1";
|
|
13836
|
+
const cachedComponents = cacheEnabled ? allComponents.flatMap((component) => {
|
|
13837
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13838
|
+
return resolution ? [{ component, resolution }] : [];
|
|
13839
|
+
}) : [];
|
|
13840
|
+
if (cacheEnabled && opts.restoreCache) {
|
|
13841
|
+
const restorations = [];
|
|
13842
|
+
const rekeyed = [];
|
|
13843
|
+
const componentStatus = db.prepare(
|
|
13844
|
+
"SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?"
|
|
13845
|
+
);
|
|
13846
|
+
for (const { component, resolution } of cachedComponents) {
|
|
13847
|
+
const current = componentStatus.get(sessionId2, component.component_id);
|
|
13848
|
+
if (current?.status === "generated") continue;
|
|
13849
|
+
renameEmptySlots(db, sessionId2, component.component_id, component.name, component.slots.length);
|
|
13850
|
+
restorations.push({
|
|
13851
|
+
sourceSessionId: resolution.entry.sourceSessionId,
|
|
13852
|
+
targetSessionId: sessionId2,
|
|
13853
|
+
componentId: component.component_id
|
|
13854
|
+
});
|
|
13855
|
+
rekeyed.push({ component, cached: resolution.entry });
|
|
13856
|
+
}
|
|
13857
|
+
copyComponentsFromCache(db, restorations, { allowedComponentNames: allowedComponentNames2 });
|
|
13858
|
+
storeCaches(
|
|
13859
|
+
db,
|
|
13860
|
+
rekeyed.map(({ component, cached }) => ({
|
|
13861
|
+
inputHash: hashComponentShape(normalizeComponentForCache(component)),
|
|
13862
|
+
entityType: "component",
|
|
13863
|
+
entityId: component.component_id,
|
|
13864
|
+
sourceSessionId: cached.sourceSessionId,
|
|
13865
|
+
humanEdited: cached.humanEdited,
|
|
13866
|
+
promptHash
|
|
13867
|
+
}))
|
|
13868
|
+
);
|
|
13869
|
+
}
|
|
13870
|
+
const fullyCached = cacheEnabled && cachedComponents.length === allComponents.length;
|
|
13871
|
+
process.stdout.write(`cache-status=${fullyCached ? "hit" : "miss"}
|
|
13872
|
+
`);
|
|
13873
|
+
process.stdout.write(
|
|
13874
|
+
`cache-components=${JSON.stringify(cachedComponents.map(({ component }) => component.name))}
|
|
13875
|
+
`
|
|
13876
|
+
);
|
|
13877
|
+
await exitWithAnalytics(0);
|
|
13878
|
+
return;
|
|
13879
|
+
}
|
|
13124
13880
|
componentResults = await runAllComponents(
|
|
13125
13881
|
{
|
|
13126
13882
|
agent,
|
|
@@ -13130,10 +13886,13 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13130
13886
|
tokensInline,
|
|
13131
13887
|
tokenMapInline,
|
|
13132
13888
|
verbose,
|
|
13889
|
+
noCache: opts.cache === false || process.env.EDS_NO_CACHE === "1",
|
|
13133
13890
|
skillPathOverride: generatePromptPath,
|
|
13134
13891
|
skillContentOverride: generatePrompt,
|
|
13892
|
+
promptHash,
|
|
13135
13893
|
existingContentfulEntities,
|
|
13136
13894
|
existingTokensInline,
|
|
13895
|
+
precomputedCachedNames,
|
|
13137
13896
|
allowedComponentNames: allowedComponentNames2
|
|
13138
13897
|
},
|
|
13139
13898
|
allComponents
|
|
@@ -13142,7 +13901,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13142
13901
|
db.close();
|
|
13143
13902
|
}
|
|
13144
13903
|
const failed = componentResults.filter((r) => r.failed);
|
|
13145
|
-
const
|
|
13904
|
+
const cachedResults = componentResults.filter((r) => r.cached);
|
|
13905
|
+
const generated = componentResults.filter((r) => !r.failed && !r.cached);
|
|
13146
13906
|
const allWarnings = componentResults.flatMap((r) => r.warnings.map((w) => ` ${r.componentName}: ${w}`));
|
|
13147
13907
|
if (allWarnings.length > 0) {
|
|
13148
13908
|
process.stderr.write(c.yellow("Warnings:") + "\n" + allWarnings.join("\n") + "\n");
|
|
@@ -13158,17 +13918,21 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13158
13918
|
const totalExcluded = generated.reduce((s, r) => s + r.excluded, 0);
|
|
13159
13919
|
const totalRenamedSlots = componentResults.reduce((s, r) => s + r.renamedSlotsCount, 0);
|
|
13160
13920
|
const allOk = failed.length === 0;
|
|
13921
|
+
const cachedNote = cachedResults.length > 0 ? c.dim(` (${cachedResults.length} cached)`) : "";
|
|
13161
13922
|
process.stderr.write(
|
|
13162
|
-
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length}/${componentResults.length} components` + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13923
|
+
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length + cachedResults.length}/${componentResults.length} components` + cachedNote + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13163
13924
|
);
|
|
13164
13925
|
process.stdout.write(`renamed-slots: ${totalRenamedSlots}
|
|
13165
13926
|
`);
|
|
13166
|
-
if (generated.length === 0) {
|
|
13927
|
+
if (generated.length === 0 && cachedResults.length === 0) {
|
|
13167
13928
|
die(
|
|
13168
13929
|
`Error: all ${componentResults.length} component(s) failed to generate \u2014 see the per-component errors above.`
|
|
13169
13930
|
);
|
|
13170
13931
|
}
|
|
13171
13932
|
} else if (skill === "tokens") {
|
|
13933
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
13934
|
+
const tokenInputContent = rawTokensInline ?? "";
|
|
13935
|
+
const tokenInputHash = hashTokenContent(tokenInputContent);
|
|
13172
13936
|
const db = openPipelineDb();
|
|
13173
13937
|
try {
|
|
13174
13938
|
let resolvedSessionId = opts.session;
|
|
@@ -13195,11 +13959,26 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13195
13959
|
}
|
|
13196
13960
|
sessionId2 = resolvedSessionId;
|
|
13197
13961
|
await bindAnalyticsSessionId(resolvedSessionId);
|
|
13962
|
+
const tokenPromptHash = await hashPromptForSkill("tokens", agent, model);
|
|
13963
|
+
if (!noCache) {
|
|
13964
|
+
const tokenCached = lookupCache(db, tokenInputHash, "token_set", "__tokens__", tokenPromptHash);
|
|
13965
|
+
if (tokenCached) {
|
|
13966
|
+
copyTokensFromCache(db, tokenCached.sourceSessionId, resolvedSessionId);
|
|
13967
|
+
sessionId2 = resolvedSessionId;
|
|
13968
|
+
process.stderr.write(
|
|
13969
|
+
`Done: tokens reused from cache ${c.dim(`(source: ${tokenCached.sourceSessionId.slice(0, 12)})`)}
|
|
13970
|
+
`
|
|
13971
|
+
);
|
|
13972
|
+
db.close();
|
|
13973
|
+
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13974
|
+
return;
|
|
13975
|
+
}
|
|
13976
|
+
}
|
|
13198
13977
|
const prompt = await buildPrompt({
|
|
13199
13978
|
skill,
|
|
13200
13979
|
mode: "autonomous",
|
|
13201
13980
|
rawTokensInline,
|
|
13202
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13981
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13203
13982
|
tokensInline,
|
|
13204
13983
|
tokenMapInline,
|
|
13205
13984
|
outDir: process.cwd()
|
|
@@ -13236,6 +14015,9 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13236
14015
|
`);
|
|
13237
14016
|
}
|
|
13238
14017
|
applyTokenToolCalls(db, resolvedSessionId, tokenCalls, []);
|
|
14018
|
+
if (!noCache) {
|
|
14019
|
+
storeCache(db, tokenInputHash, "token_set", "__tokens__", resolvedSessionId, false, tokenPromptHash);
|
|
14020
|
+
}
|
|
13239
14021
|
sessionId2 = resolvedSessionId;
|
|
13240
14022
|
const groupCount = tokenCalls.filter((tc) => tc.tool === "set_group").length;
|
|
13241
14023
|
process.stderr.write(`Done: ${tokenCount} tokens, ${groupCount} groups stored
|
|
@@ -13247,7 +14029,10 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13247
14029
|
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13248
14030
|
}
|
|
13249
14031
|
function addAgentFlags(cmd) {
|
|
13250
|
-
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent")
|
|
14032
|
+
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent").option(
|
|
14033
|
+
"--no-cache",
|
|
14034
|
+
"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."
|
|
14035
|
+
);
|
|
13251
14036
|
}
|
|
13252
14037
|
function registerInternalGenerateCommand(program) {
|
|
13253
14038
|
const generate = program.command("__generate", { hidden: true }).description("Internal import pipeline generation command");
|
|
@@ -13263,6 +14048,12 @@ function registerInternalGenerateCommand(program) {
|
|
|
13263
14048
|
"--existing-entities-path <path>",
|
|
13264
14049
|
"Path to the .existing-entities.json file written after CMA credentials are supplied. When present, per-component prompts include a summary of the target space so classifications can align to existing prop names/tokens. Missing/malformed files are treated as no-op."
|
|
13265
14050
|
);
|
|
14051
|
+
componentsCmd.option("--cache-status", "Check whether all selected component definitions are cached");
|
|
14052
|
+
componentsCmd.option("--restore-cache", "Restore cached component definitions into the current session");
|
|
14053
|
+
componentsCmd.option(
|
|
14054
|
+
"--cached-components <json>",
|
|
14055
|
+
"Component names already restored by a prior cache-status lookup; skip per-component cache lookup"
|
|
14056
|
+
);
|
|
13266
14057
|
addAgentFlags(componentsCmd).action(async (opts) => {
|
|
13267
14058
|
await runGenerateSkill("components", opts, opts.verbose ?? false);
|
|
13268
14059
|
});
|
|
@@ -13290,6 +14081,7 @@ var init_command = __esm({
|
|
|
13290
14081
|
init_agent_output();
|
|
13291
14082
|
init_GenerateView();
|
|
13292
14083
|
init_db();
|
|
14084
|
+
init_cache_keys();
|
|
13293
14085
|
init_read_existing_contentful_entities_from_session();
|
|
13294
14086
|
init_summarize_existing_contentful_entities();
|
|
13295
14087
|
init_resolve_session_id();
|
|
@@ -14005,7 +14797,7 @@ var init_user_agent = __esm({
|
|
|
14005
14797
|
// packages/experience-design-system-cli-legacy/src/apply/api-client.ts
|
|
14006
14798
|
import { parseCDFComponents } from "@contentful/experience-design-system-types";
|
|
14007
14799
|
function defaultSleep(delayMs) {
|
|
14008
|
-
return new Promise((
|
|
14800
|
+
return new Promise((resolve22) => setTimeout(resolve22, delayMs));
|
|
14009
14801
|
}
|
|
14010
14802
|
function isTransientStatus(status) {
|
|
14011
14803
|
return status >= 500 && status <= 599;
|
|
@@ -14395,7 +15187,7 @@ ${trimmed}`;
|
|
|
14395
15187
|
const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
|
|
14396
15188
|
const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
|
|
14397
15189
|
const jitter = Math.random() * baseDelay * 0.15;
|
|
14398
|
-
await new Promise((
|
|
15190
|
+
await new Promise((resolve22) => setTimeout(resolve22, baseDelay + jitter));
|
|
14399
15191
|
}
|
|
14400
15192
|
}
|
|
14401
15193
|
throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
|
|
@@ -15205,7 +15997,7 @@ var init_terminal_capabilities = __esm({
|
|
|
15205
15997
|
|
|
15206
15998
|
// packages/experience-design-system-cli-legacy/src/apply/command.ts
|
|
15207
15999
|
import { createElement as createElement2 } from "react";
|
|
15208
|
-
import { readFile as
|
|
16000
|
+
import { readFile as readFile13, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
15209
16001
|
import { join as join16 } from "node:path";
|
|
15210
16002
|
import {
|
|
15211
16003
|
validateCDF,
|
|
@@ -15226,7 +16018,7 @@ function dieWithApiError(error) {
|
|
|
15226
16018
|
async function readJsonFile(flag, p) {
|
|
15227
16019
|
let text;
|
|
15228
16020
|
try {
|
|
15229
|
-
text = await
|
|
16021
|
+
text = await readFile13(p, "utf8");
|
|
15230
16022
|
} catch {
|
|
15231
16023
|
return await die2(`Error: file not found: ${p} (from ${flag})`);
|
|
15232
16024
|
}
|
|
@@ -15280,7 +16072,7 @@ async function readTokensFromPath(flag, p) {
|
|
|
15280
16072
|
for (const file of files.sort()) {
|
|
15281
16073
|
let text;
|
|
15282
16074
|
try {
|
|
15283
|
-
text = await
|
|
16075
|
+
text = await readFile13(file, "utf8");
|
|
15284
16076
|
} catch {
|
|
15285
16077
|
continue;
|
|
15286
16078
|
}
|
|
@@ -15649,11 +16441,11 @@ var init_command2 = __esm({
|
|
|
15649
16441
|
});
|
|
15650
16442
|
|
|
15651
16443
|
// packages/experience-design-system-cli-legacy/src/print/validate/validators/read-json-file.ts
|
|
15652
|
-
import { readFile as
|
|
16444
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
15653
16445
|
async function readJsonFile2(filePath) {
|
|
15654
16446
|
let content;
|
|
15655
16447
|
try {
|
|
15656
|
-
content = await
|
|
16448
|
+
content = await readFile14(filePath, "utf-8");
|
|
15657
16449
|
} catch (err) {
|
|
15658
16450
|
return {
|
|
15659
16451
|
ok: false,
|
|
@@ -16064,7 +16856,7 @@ var init_ValidateView = __esm({
|
|
|
16064
16856
|
// packages/experience-design-system-cli-legacy/src/print/command.ts
|
|
16065
16857
|
import { createElement as createElement3 } from "react";
|
|
16066
16858
|
import { access as access3, mkdir as mkdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
16067
|
-
import { basename as basename5, resolve as
|
|
16859
|
+
import { basename as basename5, resolve as resolve13 } from "node:path";
|
|
16068
16860
|
import { CDF_SCHEMA_URL } from "@contentful/experience-design-system-types";
|
|
16069
16861
|
async function die3(message) {
|
|
16070
16862
|
process.stderr.write(`${message}
|
|
@@ -16131,7 +16923,7 @@ function registerPrintCommand(program) {
|
|
|
16131
16923
|
"--allow-empty",
|
|
16132
16924
|
"Write an empty-but-present CDF file when no components are accepted (a subsequent push then removes ALL components from the target space). Without this, an empty accepted set is an error."
|
|
16133
16925
|
).action(async (opts) => {
|
|
16134
|
-
const outPath =
|
|
16926
|
+
const outPath = resolve13(opts.out);
|
|
16135
16927
|
await assertOutIsNotDirectory(outPath);
|
|
16136
16928
|
const sessionId2 = await resolveSession(opts.session, "generate components");
|
|
16137
16929
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16179,7 +16971,7 @@ function registerPrintCommand(program) {
|
|
|
16179
16971
|
`
|
|
16180
16972
|
);
|
|
16181
16973
|
}
|
|
16182
|
-
await mkdir3(
|
|
16974
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16183
16975
|
await writeFile3(outPath, `${JSON.stringify(cdfObj, null, 2)}
|
|
16184
16976
|
`);
|
|
16185
16977
|
process.stdout.write(
|
|
@@ -16188,7 +16980,7 @@ function registerPrintCommand(program) {
|
|
|
16188
16980
|
);
|
|
16189
16981
|
});
|
|
16190
16982
|
print.command("tokens").description("Write generated tokens to a DTCG JSON file").option("--session <id>", "Session ID to print from (default: most recent generate tokens session)").option("--out <path>", "Output file path", "tokens.json").action(async (opts) => {
|
|
16191
|
-
const outPath =
|
|
16983
|
+
const outPath = resolve13(opts.out);
|
|
16192
16984
|
await assertOutIsNotDirectory(outPath);
|
|
16193
16985
|
const sessionId2 = await resolveSession(opts.session, "generate tokens");
|
|
16194
16986
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16203,7 +16995,7 @@ function registerPrintCommand(program) {
|
|
|
16203
16995
|
await die3(`Error: no generated tokens in session '${sessionId2}'. Run generate tokens first.`);
|
|
16204
16996
|
}
|
|
16205
16997
|
const tree = rebuildDTCGTree(result.groups, result.tokens);
|
|
16206
|
-
await mkdir3(
|
|
16998
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16207
16999
|
await writeFile3(outPath, `${JSON.stringify(tree, null, 2)}
|
|
16208
17000
|
`);
|
|
16209
17001
|
process.stdout.write(
|
|
@@ -16352,7 +17144,7 @@ function MapTokensView({ result, onExit }) {
|
|
|
16352
17144
|
const timer = setTimeout(onExit, 100);
|
|
16353
17145
|
return () => clearTimeout(timer);
|
|
16354
17146
|
}, [onExit]);
|
|
16355
|
-
const summary = `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
17147
|
+
const summary = result.cached ? "reused from cache" : `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
16356
17148
|
return /* @__PURE__ */ jsx8(
|
|
16357
17149
|
CommandCompletionView,
|
|
16358
17150
|
{
|
|
@@ -16486,8 +17278,8 @@ var init_resolve_defaults = __esm({
|
|
|
16486
17278
|
|
|
16487
17279
|
// packages/experience-design-system-cli-legacy/src/map-tokens/command.ts
|
|
16488
17280
|
import { createElement as createElement4 } from "react";
|
|
16489
|
-
import { readFile as
|
|
16490
|
-
import { resolve as
|
|
17281
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
17282
|
+
import { resolve as resolve14 } from "node:path";
|
|
16491
17283
|
async function renderResult(result) {
|
|
16492
17284
|
if (process.stdout.isTTY) {
|
|
16493
17285
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -16495,13 +17287,12 @@ async function renderResult(result) {
|
|
|
16495
17287
|
);
|
|
16496
17288
|
await waitUntilExit();
|
|
16497
17289
|
} else {
|
|
16498
|
-
|
|
16499
|
-
|
|
17290
|
+
const summary = result.cached ? "cached" : `${result.applied} mapping(s) applied`;
|
|
17291
|
+
process.stdout.write(`map tokens complete
|
|
16500
17292
|
agent: ${result.agent}
|
|
16501
17293
|
session=${result.sessionId}
|
|
16502
|
-
${
|
|
16503
|
-
`
|
|
16504
|
-
);
|
|
17294
|
+
${summary}
|
|
17295
|
+
`);
|
|
16505
17296
|
await exitWithAnalytics(0);
|
|
16506
17297
|
}
|
|
16507
17298
|
}
|
|
@@ -16523,7 +17314,7 @@ async function runMapTokens(opts) {
|
|
|
16523
17314
|
let mapPromptPath;
|
|
16524
17315
|
if (mapPromptOverride?.kind === "text") mapPromptText = mapPromptOverride.value;
|
|
16525
17316
|
if (mapPromptOverride?.kind === "path") {
|
|
16526
|
-
mapPromptPath =
|
|
17317
|
+
mapPromptPath = resolve14(mapPromptOverride.value);
|
|
16527
17318
|
try {
|
|
16528
17319
|
await resolvePromptOverride(mapPromptOverride);
|
|
16529
17320
|
} catch (error) {
|
|
@@ -16543,7 +17334,7 @@ async function runMapTokens(opts) {
|
|
|
16543
17334
|
const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
|
|
16544
17335
|
const tokenMapDiagnostics = [];
|
|
16545
17336
|
if (opts.tokenMap) {
|
|
16546
|
-
const fileMappings = JSON.parse(await
|
|
17337
|
+
const fileMappings = JSON.parse(await readFile15(opts.tokenMap, "utf8"));
|
|
16547
17338
|
const validMappings = {};
|
|
16548
17339
|
for (const [rawName, path] of Object.entries(fileMappings)) {
|
|
16549
17340
|
if (knownTokenPaths.has(path)) {
|
|
@@ -16621,7 +17412,7 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16621
17412
|
let existingTokensInline;
|
|
16622
17413
|
if (opts.existingEntitiesPath) {
|
|
16623
17414
|
const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
16624
|
-
|
|
17415
|
+
resolve14(opts.existingEntitiesPath)
|
|
16625
17416
|
);
|
|
16626
17417
|
if (existingContentfulEntities) {
|
|
16627
17418
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
@@ -16656,10 +17447,30 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16656
17447
|
skipAgent: "true"
|
|
16657
17448
|
});
|
|
16658
17449
|
updateStep(db, stepId2, "complete", { applied: "0", skipAgent: "true" });
|
|
16659
|
-
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0 });
|
|
17450
|
+
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0, cached: false });
|
|
16660
17451
|
return;
|
|
16661
17452
|
}
|
|
16662
17453
|
const agent = configuredAgent;
|
|
17454
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
17455
|
+
const promptHash = await hashPromptForSkill(
|
|
17456
|
+
"map-tokens",
|
|
17457
|
+
agent,
|
|
17458
|
+
model,
|
|
17459
|
+
void 0,
|
|
17460
|
+
existingTokensInline ? [hashContent(existingTokensInline)] : [],
|
|
17461
|
+
mapPromptText
|
|
17462
|
+
);
|
|
17463
|
+
const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
|
|
17464
|
+
if (!noCache) {
|
|
17465
|
+
const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
|
|
17466
|
+
if (cached) {
|
|
17467
|
+
const appliedFromCache = copyMapTokensFromCache(db, cached.sourceSessionId, sessionId2);
|
|
17468
|
+
const stepId2 = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
|
|
17469
|
+
updateStep(db, stepId2, "complete", { cached: "true", applied: String(appliedFromCache) });
|
|
17470
|
+
await renderResult({ agent, sessionId: sessionId2, applied: appliedFromCache, cached: true });
|
|
17471
|
+
return;
|
|
17472
|
+
}
|
|
17473
|
+
}
|
|
16663
17474
|
const binary = resolveAgentBinary(agent);
|
|
16664
17475
|
if (!await assertBinaryInPath(binary)) {
|
|
16665
17476
|
die(
|
|
@@ -16679,20 +17490,23 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
16679
17490
|
}
|
|
16680
17491
|
const { calls, warnings: parseWarnings } = parseMapTokenPropToolCallLines(result.stdout);
|
|
16681
17492
|
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, calls, parseWarnings);
|
|
17493
|
+
if (!noCache) {
|
|
17494
|
+
storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId2, false, promptHash);
|
|
17495
|
+
}
|
|
16682
17496
|
updateStep(db, stepId, "complete", { applied: String(applied), warnings: String(warnings.length) });
|
|
16683
17497
|
if (warnings.length > 0) {
|
|
16684
17498
|
process.stderr.write(`Warnings:
|
|
16685
17499
|
${warnings.map((w) => ` ${w}`).join("\n")}
|
|
16686
17500
|
`);
|
|
16687
17501
|
}
|
|
16688
|
-
await renderResult({ agent, sessionId: sessionId2, applied });
|
|
17502
|
+
await renderResult({ agent, sessionId: sessionId2, applied, cached: false });
|
|
16689
17503
|
} finally {
|
|
16690
17504
|
db.close();
|
|
16691
17505
|
}
|
|
16692
17506
|
}
|
|
16693
17507
|
function registerMapTokensCommand(program) {
|
|
16694
17508
|
const map = program.command("map", { hidden: true }).description("Suggest token restrictions for generated design-token props");
|
|
16695
|
-
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option(
|
|
17509
|
+
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option("--no-cache", "Bypass the map-tokens cache and force a re-run").option(
|
|
16696
17510
|
"--prompt <stage=value>",
|
|
16697
17511
|
"Override a stage prompt (repeatable). Used here for the map-tokens stage.",
|
|
16698
17512
|
(v, acc) => [...acc, v],
|
|
@@ -16712,6 +17526,7 @@ var init_command4 = __esm({
|
|
|
16712
17526
|
init_render_with_goodbye();
|
|
16713
17527
|
init_src();
|
|
16714
17528
|
init_db();
|
|
17529
|
+
init_cache_keys();
|
|
16715
17530
|
init_read_existing_contentful_entities_from_session();
|
|
16716
17531
|
init_summarize_existing_contentful_entities();
|
|
16717
17532
|
init_command3();
|
|
@@ -16728,7 +17543,7 @@ var init_command4 = __esm({
|
|
|
16728
17543
|
});
|
|
16729
17544
|
|
|
16730
17545
|
// packages/experience-design-system-cli-legacy/src/import/path-utils.ts
|
|
16731
|
-
import { resolve as
|
|
17546
|
+
import { resolve as resolve15 } from "node:path";
|
|
16732
17547
|
import { homedir as homedir5 } from "node:os";
|
|
16733
17548
|
function expandTilde(input) {
|
|
16734
17549
|
if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
|
|
@@ -16742,7 +17557,7 @@ function normalizePath(input) {
|
|
|
16742
17557
|
p = p.slice(1, -1);
|
|
16743
17558
|
}
|
|
16744
17559
|
p = expandTilde(p);
|
|
16745
|
-
return
|
|
17560
|
+
return resolve15(p);
|
|
16746
17561
|
}
|
|
16747
17562
|
var init_path_utils = __esm({
|
|
16748
17563
|
"packages/experience-design-system-cli-legacy/src/import/path-utils.ts"() {
|
|
@@ -16967,7 +17782,7 @@ var init_save_path_resolver = __esm({
|
|
|
16967
17782
|
});
|
|
16968
17783
|
|
|
16969
17784
|
// packages/experience-design-system-cli-legacy/src/runs/store.ts
|
|
16970
|
-
import { readFile as
|
|
17785
|
+
import { readFile as readFile16, writeFile as writeFile4, mkdir as mkdir4, rename } from "node:fs/promises";
|
|
16971
17786
|
import { join as join20 } from "node:path";
|
|
16972
17787
|
import { homedir as homedir6 } from "node:os";
|
|
16973
17788
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -17007,7 +17822,7 @@ function migrateRecord(rec) {
|
|
|
17007
17822
|
}
|
|
17008
17823
|
async function readFileMaybe() {
|
|
17009
17824
|
try {
|
|
17010
|
-
const raw = await
|
|
17825
|
+
const raw = await readFile16(RUNS_PATH, "utf8");
|
|
17011
17826
|
const parsed = JSON.parse(raw);
|
|
17012
17827
|
if (!READABLE_VERSIONS.has(parsed.version)) {
|
|
17013
17828
|
throw new Error(
|
|
@@ -17071,15 +17886,15 @@ var init_store = __esm({
|
|
|
17071
17886
|
});
|
|
17072
17887
|
|
|
17073
17888
|
// packages/experience-design-system-cli-legacy/src/runs/fingerprint.ts
|
|
17074
|
-
import { createHash as
|
|
17075
|
-
import { readFile as
|
|
17076
|
-
import { resolve as
|
|
17889
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
17890
|
+
import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
|
|
17891
|
+
import { resolve as resolve16 } from "node:path";
|
|
17077
17892
|
function rowField(row, key) {
|
|
17078
17893
|
const v = row[key];
|
|
17079
17894
|
return typeof v === "string" ? v : null;
|
|
17080
17895
|
}
|
|
17081
17896
|
function sha256Hex(buf) {
|
|
17082
|
-
return
|
|
17897
|
+
return createHash6("sha256").update(buf).digest("hex");
|
|
17083
17898
|
}
|
|
17084
17899
|
async function buildSourceFingerprint(opts) {
|
|
17085
17900
|
const rows = opts.db.prepare("SELECT name, source_path FROM raw_components WHERE session_id = ?").all(opts.extractSessionId);
|
|
@@ -17089,7 +17904,7 @@ async function buildSourceFingerprint(opts) {
|
|
|
17089
17904
|
const sourcePath = rowField(row, "source_path");
|
|
17090
17905
|
const name = rowField(row, "name");
|
|
17091
17906
|
if (!sourcePath) continue;
|
|
17092
|
-
const abs =
|
|
17907
|
+
const abs = resolve16(sourcePath);
|
|
17093
17908
|
if (seen.has(abs)) continue;
|
|
17094
17909
|
seen.add(abs);
|
|
17095
17910
|
try {
|
|
@@ -17104,10 +17919,10 @@ async function buildSourceFingerprint(opts) {
|
|
|
17104
17919
|
let rawTokensMtime = null;
|
|
17105
17920
|
let rawTokensContentHash = null;
|
|
17106
17921
|
if (opts.rawTokensPath) {
|
|
17107
|
-
const abs =
|
|
17922
|
+
const abs = resolve16(opts.rawTokensPath);
|
|
17108
17923
|
rawTokensPath = abs;
|
|
17109
17924
|
try {
|
|
17110
|
-
const [st, buf] = await Promise.all([stat4(abs),
|
|
17925
|
+
const [st, buf] = await Promise.all([stat4(abs), readFile17(abs)]);
|
|
17111
17926
|
rawTokensMtime = st.mtime.toISOString();
|
|
17112
17927
|
rawTokensContentHash = sha256Hex(buf);
|
|
17113
17928
|
} catch {
|
|
@@ -18862,11 +19677,11 @@ var init_slot_graph = __esm({
|
|
|
18862
19677
|
});
|
|
18863
19678
|
|
|
18864
19679
|
// packages/experience-design-system-cli-legacy/src/analyze/select/parser.ts
|
|
18865
|
-
import { createHash as
|
|
19680
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
18866
19681
|
import { access as access5 } from "node:fs/promises";
|
|
18867
|
-
import { isAbsolute, relative, resolve as
|
|
19682
|
+
import { isAbsolute, relative, resolve as resolve17 } from "node:path";
|
|
18868
19683
|
function createComponentId(name, resolvedSourcePath) {
|
|
18869
|
-
const sourceHash =
|
|
19684
|
+
const sourceHash = createHash7("sha256").update(`${name}:${resolvedSourcePath}`).digest("hex").slice(0, 12);
|
|
18870
19685
|
return `${name}-${sourceHash}`;
|
|
18871
19686
|
}
|
|
18872
19687
|
async function resolveComponentSourcePath(source, reviewRoot) {
|
|
@@ -18878,7 +19693,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18878
19693
|
throw new Error(`Unable to access component source at ${source}`);
|
|
18879
19694
|
}
|
|
18880
19695
|
}
|
|
18881
|
-
const candidate =
|
|
19696
|
+
const candidate = resolve17(reviewRoot, source);
|
|
18882
19697
|
const relativeToRoot = relative(reviewRoot, candidate);
|
|
18883
19698
|
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || isAbsolute(relativeToRoot)) {
|
|
18884
19699
|
throw new Error(
|
|
@@ -18893,7 +19708,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18893
19708
|
}
|
|
18894
19709
|
}
|
|
18895
19710
|
async function loadReviewInput(components, options = {}) {
|
|
18896
|
-
const reviewRoot =
|
|
19711
|
+
const reviewRoot = resolve17(options.reviewRoot ?? process.cwd());
|
|
18897
19712
|
const records = await Promise.all(
|
|
18898
19713
|
components.map(async (component) => {
|
|
18899
19714
|
let resolvedSourcePath;
|
|
@@ -18924,7 +19739,7 @@ var init_parser = __esm({
|
|
|
18924
19739
|
});
|
|
18925
19740
|
|
|
18926
19741
|
// packages/experience-design-system-cli-legacy/src/analyze/select/command.ts
|
|
18927
|
-
import { access as access6, readFile as
|
|
19742
|
+
import { access as access6, readFile as readFile18 } from "node:fs/promises";
|
|
18928
19743
|
async function loadAndValidateForReview(sessionId2, projectRoot) {
|
|
18929
19744
|
const db = openPipelineDb();
|
|
18930
19745
|
let rawComponents;
|
|
@@ -18942,7 +19757,7 @@ async function patchReviewStateWithValidationErrors(sessionId2, errors, opts = {
|
|
|
18942
19757
|
let snapshot;
|
|
18943
19758
|
try {
|
|
18944
19759
|
await access6(paths.statePath);
|
|
18945
|
-
snapshot = JSON.parse(await
|
|
19760
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18946
19761
|
} catch {
|
|
18947
19762
|
snapshot = await loadAndValidateForReview(sessionId2, void 0);
|
|
18948
19763
|
snapshot = await ensureRefineSession(sessionId2, artifactsRoot, snapshot);
|
|
@@ -18993,7 +19808,7 @@ async function rejectComponentsByName(sessionId2, names, opts = {}) {
|
|
|
18993
19808
|
const nameSet = new Set(names);
|
|
18994
19809
|
let snapshot;
|
|
18995
19810
|
try {
|
|
18996
|
-
snapshot = JSON.parse(await
|
|
19811
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18997
19812
|
} catch {
|
|
18998
19813
|
return;
|
|
18999
19814
|
}
|
|
@@ -19092,9 +19907,9 @@ function spawnGenerateChild(opts) {
|
|
|
19092
19907
|
stderr += chunk;
|
|
19093
19908
|
opts.onStderr?.(chunk);
|
|
19094
19909
|
});
|
|
19095
|
-
const donePromise = new Promise((
|
|
19910
|
+
const donePromise = new Promise((resolve22) => {
|
|
19096
19911
|
child.on("close", (code, signal) => {
|
|
19097
|
-
|
|
19912
|
+
resolve22({
|
|
19098
19913
|
exitCode: code ?? 0,
|
|
19099
19914
|
signal: signal ?? null,
|
|
19100
19915
|
stdout,
|
|
@@ -19102,7 +19917,7 @@ function spawnGenerateChild(opts) {
|
|
|
19102
19917
|
});
|
|
19103
19918
|
});
|
|
19104
19919
|
child.on("error", (err) => {
|
|
19105
|
-
|
|
19920
|
+
resolve22({
|
|
19106
19921
|
exitCode: 1,
|
|
19107
19922
|
signal: null,
|
|
19108
19923
|
stdout,
|
|
@@ -27240,6 +28055,9 @@ function shouldGenerateAfterCredentialsValidated(opts) {
|
|
|
27240
28055
|
function shouldSkipFinalReviewAfterCredentials(state) {
|
|
27241
28056
|
return state.finalReviewPassed && state.generateSessionId != null;
|
|
27242
28057
|
}
|
|
28058
|
+
function resolveNoCacheForGenerate(opts) {
|
|
28059
|
+
return opts.cliNoCache;
|
|
28060
|
+
}
|
|
27243
28061
|
function shouldBypassPreview(state) {
|
|
27244
28062
|
return state.credentialsSkipped === true;
|
|
27245
28063
|
}
|
|
@@ -27266,39 +28084,66 @@ var init_wizard_state_transitions = __esm({
|
|
|
27266
28084
|
async function runSelectionAgent(options) {
|
|
27267
28085
|
const db = openPipelineDb();
|
|
27268
28086
|
let components;
|
|
28087
|
+
const cachedDecisions = /* @__PURE__ */ new Map();
|
|
28088
|
+
const cliVersion2 = await getCliCacheVersion();
|
|
28089
|
+
const promptHash = await hashPromptForSkill(
|
|
28090
|
+
"select",
|
|
28091
|
+
options.agent,
|
|
28092
|
+
options.model,
|
|
28093
|
+
options.promptPath,
|
|
28094
|
+
[SELECT_PAYLOAD_FORMAT],
|
|
28095
|
+
options.promptText
|
|
28096
|
+
);
|
|
27269
28097
|
try {
|
|
27270
28098
|
components = loadRawComponents(db, options.sessionId);
|
|
28099
|
+
if (!options.noCache) {
|
|
28100
|
+
for (const component of components) {
|
|
28101
|
+
const componentHash = hashComponentShape(component);
|
|
28102
|
+
const cached = lookupSelectCache(db, componentHash, promptHash, cliVersion2);
|
|
28103
|
+
if (cached) {
|
|
28104
|
+
cachedDecisions.set(component.name, {
|
|
28105
|
+
decision: cached.decision,
|
|
28106
|
+
reason: cached.reason
|
|
28107
|
+
});
|
|
28108
|
+
}
|
|
28109
|
+
}
|
|
28110
|
+
}
|
|
27271
28111
|
} finally {
|
|
27272
28112
|
db.close();
|
|
27273
28113
|
}
|
|
27274
28114
|
if (components.length === 0) return;
|
|
27275
|
-
const
|
|
27276
|
-
|
|
27277
|
-
|
|
27278
|
-
|
|
27279
|
-
|
|
27280
|
-
|
|
27281
|
-
|
|
27282
|
-
|
|
27283
|
-
|
|
27284
|
-
|
|
27285
|
-
|
|
27286
|
-
|
|
27287
|
-
|
|
27288
|
-
|
|
27289
|
-
|
|
27290
|
-
|
|
27291
|
-
|
|
27292
|
-
|
|
27293
|
-
|
|
27294
|
-
|
|
27295
|
-
|
|
27296
|
-
|
|
27297
|
-
|
|
27298
|
-
|
|
27299
|
-
|
|
28115
|
+
const componentsToRun = components.filter((component) => !cachedDecisions.has(component.name));
|
|
28116
|
+
let calls = [];
|
|
28117
|
+
if (componentsToRun.length > 0) {
|
|
28118
|
+
const invoker2 = createLocalCliAgentInvoker({
|
|
28119
|
+
onDebugEvent: (name, payload) => getDebugLogger().event("agent", name, payload)
|
|
28120
|
+
});
|
|
28121
|
+
const prompt = await buildPrompt({
|
|
28122
|
+
skill: "select",
|
|
28123
|
+
mode: "autonomous",
|
|
28124
|
+
rawComponentsInline: JSON.stringify(
|
|
28125
|
+
componentsToRun.map((component) => ({ ...component, props: component.props.map(stripPropProvenance) })),
|
|
28126
|
+
null,
|
|
28127
|
+
2
|
|
28128
|
+
),
|
|
28129
|
+
propBucketsInline: logPropBuckets("select", bucketComponentsProps(componentsToRun)),
|
|
28130
|
+
outDir: process.cwd(),
|
|
28131
|
+
...options.promptText !== void 0 ? { skillContentOverride: options.promptText } : {},
|
|
28132
|
+
...options.promptText === void 0 && options.promptPath ? { skillPathOverride: options.promptPath } : {}
|
|
28133
|
+
});
|
|
28134
|
+
const { result } = await invokeAgentWithOutput(
|
|
28135
|
+
invoker2,
|
|
28136
|
+
{ agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
|
|
28137
|
+
false
|
|
28138
|
+
);
|
|
28139
|
+
if (result.timedOut) throw new Error("selection agent timed out");
|
|
28140
|
+
if (result.exitCode !== 0) throw new Error(`selection agent exited with code ${result.exitCode}`);
|
|
28141
|
+
const parsed = parseSelectToolCallLines(result.stdout);
|
|
28142
|
+
for (const warning of parsed.warnings) process.stderr.write(`Warning: selection agent: ${warning}
|
|
27300
28143
|
`);
|
|
27301
|
-
|
|
28144
|
+
calls = parsed.calls;
|
|
28145
|
+
}
|
|
28146
|
+
const byName = new Map(calls.map((call) => [call.name, call]));
|
|
27302
28147
|
const writeDb = openPipelineDb();
|
|
27303
28148
|
try {
|
|
27304
28149
|
writeDb.exec("BEGIN");
|
|
@@ -27306,15 +28151,27 @@ async function runSelectionAgent(options) {
|
|
|
27306
28151
|
`UPDATE raw_components SET status = ?, reject_reason = ? WHERE session_id = ? AND component_id = ?`
|
|
27307
28152
|
);
|
|
27308
28153
|
for (const component of components) {
|
|
28154
|
+
const cached = cachedDecisions.get(component.name);
|
|
27309
28155
|
const call = byName.get(component.name);
|
|
27310
|
-
if (!call) continue;
|
|
27311
|
-
const rejected = call.tool === "reject_component";
|
|
28156
|
+
if (!cached && !call) continue;
|
|
28157
|
+
const rejected = cached ? cached.decision === "rejected" : call.tool === "reject_component";
|
|
28158
|
+
const reason = cached ? cached.reason : call.reason ?? null;
|
|
27312
28159
|
update.run(
|
|
27313
28160
|
rejected ? "rejected" : "accepted",
|
|
27314
|
-
rejected ?
|
|
28161
|
+
rejected ? reason : null,
|
|
27315
28162
|
options.sessionId,
|
|
27316
28163
|
component.component_id
|
|
27317
28164
|
);
|
|
28165
|
+
if (!cached) {
|
|
28166
|
+
storeSelectCache(
|
|
28167
|
+
writeDb,
|
|
28168
|
+
hashComponentShape(component),
|
|
28169
|
+
promptHash,
|
|
28170
|
+
cliVersion2,
|
|
28171
|
+
rejected ? "rejected" : "accepted",
|
|
28172
|
+
rejected ? reason : null
|
|
28173
|
+
);
|
|
28174
|
+
}
|
|
27318
28175
|
}
|
|
27319
28176
|
writeDb.exec("COMMIT");
|
|
27320
28177
|
} catch (error) {
|
|
@@ -27324,7 +28181,7 @@ async function runSelectionAgent(options) {
|
|
|
27324
28181
|
writeDb.close();
|
|
27325
28182
|
}
|
|
27326
28183
|
}
|
|
27327
|
-
var DEFAULT_TIMEOUT_MS4;
|
|
28184
|
+
var SELECT_PAYLOAD_FORMAT, DEFAULT_TIMEOUT_MS4;
|
|
27328
28185
|
var init_run_selection_agent = __esm({
|
|
27329
28186
|
"packages/experience-design-system-cli-legacy/src/import/tui/run-selection-agent.ts"() {
|
|
27330
28187
|
"use strict";
|
|
@@ -27335,6 +28192,8 @@ var init_run_selection_agent = __esm({
|
|
|
27335
28192
|
init_debug_logger();
|
|
27336
28193
|
init_agent_output();
|
|
27337
28194
|
init_db();
|
|
28195
|
+
init_cache_keys();
|
|
28196
|
+
SELECT_PAYLOAD_FORMAT = "prop-buckets-v1";
|
|
27338
28197
|
DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
|
|
27339
28198
|
}
|
|
27340
28199
|
});
|
|
@@ -27353,7 +28212,7 @@ __export(WizardApp_exports, {
|
|
|
27353
28212
|
});
|
|
27354
28213
|
import { useEffect as useEffect15, useRef as useRef10, useState as useState23 } from "react";
|
|
27355
28214
|
import { Box as Box42, Text as Text46 } from "ink";
|
|
27356
|
-
import { join as join23, resolve as
|
|
28215
|
+
import { join as join23, resolve as resolve18 } from "node:path";
|
|
27357
28216
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27358
28217
|
import { access as access7, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
27359
28218
|
import { tmpdir } from "node:os";
|
|
@@ -27366,21 +28225,28 @@ function buildGenerateComponentsArgs(opts) {
|
|
|
27366
28225
|
if (opts.tokensPath) args.push("--tokens", opts.tokensPath);
|
|
27367
28226
|
if (opts.model) args.push("--model", opts.model);
|
|
27368
28227
|
if (opts.bedrock) args.push("--bedrock");
|
|
28228
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27369
28229
|
if (opts.generatePromptPath) args.push("--generate-prompt-path", opts.generatePromptPath);
|
|
27370
28230
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27371
28231
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
28232
|
+
if (opts.restoreCache) args.push("--restore-cache");
|
|
28233
|
+
if (opts.cachedComponents && opts.cachedComponents.length > 0) {
|
|
28234
|
+
args.push("--cached-components", JSON.stringify(opts.cachedComponents));
|
|
28235
|
+
}
|
|
27372
28236
|
return args;
|
|
27373
28237
|
}
|
|
27374
28238
|
function buildGenerateTokensArgs(opts) {
|
|
27375
28239
|
const args = [findCliPath(), "__generate", "tokens", "--agent", opts.agent, "--raw-tokens", opts.rawTokensPath];
|
|
27376
28240
|
if (opts.model) args.push("--model", opts.model);
|
|
27377
28241
|
if (opts.bedrock) args.push("--bedrock");
|
|
28242
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27378
28243
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27379
28244
|
return args;
|
|
27380
28245
|
}
|
|
27381
28246
|
function buildMapTokensArgs(opts) {
|
|
27382
28247
|
const args = ["map", "tokens", "--session", opts.sessionId, "--agent", opts.agent];
|
|
27383
28248
|
if (opts.model) args.push("--model", opts.model);
|
|
28249
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27384
28250
|
if (opts.skipAgent) args.push("--skip-agent");
|
|
27385
28251
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27386
28252
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
@@ -27472,6 +28338,7 @@ function WizardApp({
|
|
|
27472
28338
|
initialProjectPath,
|
|
27473
28339
|
host,
|
|
27474
28340
|
promptOverrides,
|
|
28341
|
+
noCache = false,
|
|
27475
28342
|
livePreview = true,
|
|
27476
28343
|
generatePromptPath,
|
|
27477
28344
|
skipMapTokens = false,
|
|
@@ -27496,6 +28363,7 @@ function WizardApp({
|
|
|
27496
28363
|
});
|
|
27497
28364
|
const allowEmptyDeleteAllRef = useRef10(false);
|
|
27498
28365
|
const generateChildRef = useRef10(null);
|
|
28366
|
+
const generationCachePreflightRef = useRef10(null);
|
|
27499
28367
|
const selectionToReviewStartedAtRef = useRef10(null);
|
|
27500
28368
|
const credentialsValidationIdRef = useRef10(0);
|
|
27501
28369
|
const pendingCredentialValidationRef = useRef10(null);
|
|
@@ -27510,8 +28378,9 @@ function WizardApp({
|
|
|
27510
28378
|
const existingEntitiesPromiseRef = useRef10(null);
|
|
27511
28379
|
const generatePromiseRef = useRef10(null);
|
|
27512
28380
|
const rawTokensEntryReady = !!initialRawTokensPath;
|
|
28381
|
+
const effectiveNoCache = resolveNoCacheForGenerate({ cliNoCache: noCache });
|
|
27513
28382
|
const initialStepResolved = rawTokensEntryReady ? initialProjectPath ? "path-validation" : "credentials" : initialProjectPath ? "token-input" : "welcome";
|
|
27514
|
-
const initialOutDir = initialProjectPath ? join23(
|
|
28383
|
+
const initialOutDir = initialProjectPath ? join23(resolve18(initialProjectPath), ".contentful") : "";
|
|
27515
28384
|
const [state, setState] = useState23({
|
|
27516
28385
|
step: initialStepResolved,
|
|
27517
28386
|
agent: initialAgent ?? "claude",
|
|
@@ -27687,13 +28556,14 @@ If you are using AWS Bedrock, run:
|
|
|
27687
28556
|
if (!deferStep) update({ step: nextStep });
|
|
27688
28557
|
return true;
|
|
27689
28558
|
};
|
|
27690
|
-
const runGenerateTokens = async (rawTokensPath, outDir) => {
|
|
28559
|
+
const runGenerateTokens = async (rawTokensPath, outDir, forceRegenerate = false) => {
|
|
27691
28560
|
update({ tokenGenerationStatus: "running" });
|
|
27692
28561
|
const tokenArgs = buildGenerateTokensArgs({
|
|
27693
28562
|
rawTokensPath,
|
|
27694
28563
|
agent: state.agent,
|
|
27695
28564
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27696
28565
|
...state.bedrock ? { bedrock: true } : {},
|
|
28566
|
+
noCache: effectiveNoCache || forceRegenerate,
|
|
27697
28567
|
promptOverrides
|
|
27698
28568
|
});
|
|
27699
28569
|
const result = await runSpawnedCli(tokenArgs);
|
|
@@ -27742,6 +28612,7 @@ If you are using AWS Bedrock, run:
|
|
|
27742
28612
|
const timer = startWizardTimer("token-mapping", {
|
|
27743
28613
|
sessionId: sessionId2,
|
|
27744
28614
|
silent,
|
|
28615
|
+
noCache: effectiveNoCache,
|
|
27745
28616
|
skipAgent: skipMapTokens
|
|
27746
28617
|
});
|
|
27747
28618
|
let mappablePropCount = 0;
|
|
@@ -27750,7 +28621,7 @@ If you are using AWS Bedrock, run:
|
|
|
27750
28621
|
const db = openPipelineDb();
|
|
27751
28622
|
try {
|
|
27752
28623
|
if (state.tokenSessionId && state.tokenSessionId !== sessionId2) {
|
|
27753
|
-
|
|
28624
|
+
copyTokensFromCache(db, state.tokenSessionId, sessionId2);
|
|
27754
28625
|
} else if (!state.tokenSessionId && state.tokensPath) {
|
|
27755
28626
|
const tokens = await readTokensFromPath("tokens", state.tokensPath);
|
|
27756
28627
|
storeDtcgTokens(db, sessionId2, [], tokens);
|
|
@@ -27790,6 +28661,7 @@ If you are using AWS Bedrock, run:
|
|
|
27790
28661
|
sessionId: sessionId2,
|
|
27791
28662
|
agent: state.agent,
|
|
27792
28663
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28664
|
+
noCache: effectiveNoCache,
|
|
27793
28665
|
skipAgent: skipMapTokens,
|
|
27794
28666
|
promptOverrides,
|
|
27795
28667
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
|
|
@@ -27869,7 +28741,7 @@ If you are using AWS Bedrock, run:
|
|
|
27869
28741
|
return promise;
|
|
27870
28742
|
};
|
|
27871
28743
|
const runExtract = async (projectPath, showProgress = true) => {
|
|
27872
|
-
const outDir = join23(
|
|
28744
|
+
const outDir = join23(resolve18(projectPath), ".contentful");
|
|
27873
28745
|
const existingEntitiesExpected = !state.credentialsSkipped && Boolean(state.spaceId && state.environmentId && state.cmaToken && projectPath);
|
|
27874
28746
|
update({
|
|
27875
28747
|
...showProgress ? { step: "extracting" } : {},
|
|
@@ -27884,6 +28756,10 @@ If you are using AWS Bedrock, run:
|
|
|
27884
28756
|
});
|
|
27885
28757
|
const existingEntitiesPromise = startExistingEntitiesFetch(projectPath, outDir);
|
|
27886
28758
|
const extractArgs = [findCliPath(), "__extract", "--project", projectPath];
|
|
28759
|
+
if (effectiveNoCache) extractArgs.push("--composition-refresh", "--no-cache");
|
|
28760
|
+
for (const p of promptOverrides ?? []) extractArgs.push("--prompt", p);
|
|
28761
|
+
if (state.agent) extractArgs.push("--agent", state.agent);
|
|
28762
|
+
if (state.bedrock) extractArgs.push("--bedrock");
|
|
27887
28763
|
let selectionPromptText;
|
|
27888
28764
|
let selectionPromptPath;
|
|
27889
28765
|
try {
|
|
@@ -27892,7 +28768,7 @@ If you are using AWS Bedrock, run:
|
|
|
27892
28768
|
const selectOverride = overrides.get("select");
|
|
27893
28769
|
if (selectOverride?.kind === "text") selectionPromptText = selectOverride.value;
|
|
27894
28770
|
if (selectOverride?.kind === "path") {
|
|
27895
|
-
selectionPromptPath =
|
|
28771
|
+
selectionPromptPath = resolve18(selectOverride.value);
|
|
27896
28772
|
await resolvePromptOverride(selectOverride);
|
|
27897
28773
|
}
|
|
27898
28774
|
} catch (error) {
|
|
@@ -27916,7 +28792,8 @@ If you are using AWS Bedrock, run:
|
|
|
27916
28792
|
agent: state.agent,
|
|
27917
28793
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27918
28794
|
...selectionPromptText !== void 0 ? { promptText: selectionPromptText } : {},
|
|
27919
|
-
...selectionPromptPath ? { promptPath: selectionPromptPath } : {}
|
|
28795
|
+
...selectionPromptPath ? { promptPath: selectionPromptPath } : {},
|
|
28796
|
+
noCache: effectiveNoCache
|
|
27920
28797
|
});
|
|
27921
28798
|
})().catch((error) => {
|
|
27922
28799
|
selectionError = error;
|
|
@@ -28061,17 +28938,136 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28061
28938
|
generateProgress: null
|
|
28062
28939
|
}));
|
|
28063
28940
|
};
|
|
28064
|
-
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2) => ({
|
|
28941
|
+
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => ({
|
|
28065
28942
|
sessionId: extractSessionId,
|
|
28066
28943
|
tokensPath,
|
|
28067
28944
|
agent: state.agent,
|
|
28068
28945
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28069
28946
|
...state.bedrock ? { bedrock: true } : {},
|
|
28947
|
+
noCache: effectiveNoCache,
|
|
28070
28948
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {},
|
|
28071
28949
|
...generatePromptPath2 ? { generatePromptPath: generatePromptPath2 } : {},
|
|
28072
|
-
promptOverrides
|
|
28950
|
+
promptOverrides,
|
|
28951
|
+
...cachedComponents && cachedComponents.length > 0 ? { cachedComponents } : {}
|
|
28073
28952
|
});
|
|
28074
|
-
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2));
|
|
28953
|
+
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents));
|
|
28954
|
+
const buildGenerateCliArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateComponentsArgs(
|
|
28955
|
+
buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents)
|
|
28956
|
+
);
|
|
28957
|
+
const checkGenerateCache = async (extractSessionId, tokensPath) => {
|
|
28958
|
+
const timer = startWizardTimer("generation-cache-status", {
|
|
28959
|
+
sessionId: extractSessionId,
|
|
28960
|
+
noCache: effectiveNoCache
|
|
28961
|
+
});
|
|
28962
|
+
if (effectiveNoCache) {
|
|
28963
|
+
finishWizardTimer("generation-cache-status", timer, { status: "skipped" });
|
|
28964
|
+
return false;
|
|
28965
|
+
}
|
|
28966
|
+
const result = await runCli([...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"]);
|
|
28967
|
+
const hit = result.exitCode === 0 && /^cache-status=hit$/m.test(result.stdout);
|
|
28968
|
+
finishWizardTimer("generation-cache-status", timer, {
|
|
28969
|
+
status: hit ? "hit" : "miss",
|
|
28970
|
+
exitCode: result.exitCode,
|
|
28971
|
+
...result.exitCode !== 0 ? { stderrTail: result.stderr.trim().slice(-500) } : {}
|
|
28972
|
+
});
|
|
28973
|
+
return hit;
|
|
28974
|
+
};
|
|
28975
|
+
const checkGenerateCacheComponents = async (extractSessionId, tokensPath, restoreCache = false) => {
|
|
28976
|
+
const timer = startWizardTimer("generation-cache-components", {
|
|
28977
|
+
sessionId: extractSessionId,
|
|
28978
|
+
restoreCache,
|
|
28979
|
+
noCache: effectiveNoCache
|
|
28980
|
+
});
|
|
28981
|
+
if (effectiveNoCache) {
|
|
28982
|
+
finishWizardTimer("generation-cache-components", timer, { status: "skipped" });
|
|
28983
|
+
return /* @__PURE__ */ new Set();
|
|
28984
|
+
}
|
|
28985
|
+
const args = [...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"];
|
|
28986
|
+
if (restoreCache) args.push("--restore-cache");
|
|
28987
|
+
const result = await runCli(args);
|
|
28988
|
+
if (result.exitCode !== 0) {
|
|
28989
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28990
|
+
status: "error",
|
|
28991
|
+
exitCode: result.exitCode,
|
|
28992
|
+
stderrTail: result.stderr.trim().slice(-500)
|
|
28993
|
+
});
|
|
28994
|
+
return /* @__PURE__ */ new Set();
|
|
28995
|
+
}
|
|
28996
|
+
const line = /^cache-components=(.+)$/m.exec(result.stdout)?.[1];
|
|
28997
|
+
if (!line) {
|
|
28998
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28999
|
+
status: "missing-output",
|
|
29000
|
+
exitCode: result.exitCode,
|
|
29001
|
+
cachedCount: 0
|
|
29002
|
+
});
|
|
29003
|
+
return /* @__PURE__ */ new Set();
|
|
29004
|
+
}
|
|
29005
|
+
try {
|
|
29006
|
+
const names = JSON.parse(line);
|
|
29007
|
+
const cachedNames = new Set(
|
|
29008
|
+
Array.isArray(names) ? names.filter((name) => typeof name === "string") : []
|
|
29009
|
+
);
|
|
29010
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
29011
|
+
status: "complete",
|
|
29012
|
+
exitCode: result.exitCode,
|
|
29013
|
+
cachedCount: cachedNames.size
|
|
29014
|
+
});
|
|
29015
|
+
return cachedNames;
|
|
29016
|
+
} catch {
|
|
29017
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
29018
|
+
status: "invalid-output",
|
|
29019
|
+
exitCode: result.exitCode,
|
|
29020
|
+
cachedCount: 0
|
|
29021
|
+
});
|
|
29022
|
+
return /* @__PURE__ */ new Set();
|
|
29023
|
+
}
|
|
29024
|
+
};
|
|
29025
|
+
useEffect15(() => {
|
|
29026
|
+
if (state.step !== "extracting" && state.step !== "scope-gate" || !state.extractSessionId || state.existingEntitiesStatus === "running" || state.existingEntitiesStatus === "idle" || state.selectionAgentStatus !== "complete" || state.compositionPhase !== "done" && state.compositionPhase !== "cache-hit" || state.rawTokensPath && state.tokenGenerationStatus !== "complete" || effectiveNoCache) {
|
|
29027
|
+
return;
|
|
29028
|
+
}
|
|
29029
|
+
const sessionId2 = state.extractSessionId;
|
|
29030
|
+
if (generationCachePreflightRef.current?.sessionId === sessionId2) return;
|
|
29031
|
+
const timer = startWizardTimer("generation-cache-preflight", { sessionId: sessionId2 });
|
|
29032
|
+
const db = openPipelineDb();
|
|
29033
|
+
let generatedNames = null;
|
|
29034
|
+
try {
|
|
29035
|
+
const rows = db.prepare("SELECT name, status FROM raw_components WHERE session_id = ?").all(sessionId2);
|
|
29036
|
+
if (rows.length > 0 && rows.every((row) => row.status === "generated")) {
|
|
29037
|
+
generatedNames = new Set(rows.map((row) => row.name));
|
|
29038
|
+
}
|
|
29039
|
+
} finally {
|
|
29040
|
+
db.close();
|
|
29041
|
+
}
|
|
29042
|
+
if (generatedNames) {
|
|
29043
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: Promise.resolve(generatedNames) };
|
|
29044
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29045
|
+
status: "complete",
|
|
29046
|
+
source: "session-db",
|
|
29047
|
+
cachedCount: generatedNames.size
|
|
29048
|
+
});
|
|
29049
|
+
return;
|
|
29050
|
+
}
|
|
29051
|
+
const promise = checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
29052
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise };
|
|
29053
|
+
void promise.then((cachedNames) => {
|
|
29054
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29055
|
+
status: "complete",
|
|
29056
|
+
source: "cache-status",
|
|
29057
|
+
cachedCount: cachedNames.size
|
|
29058
|
+
});
|
|
29059
|
+
});
|
|
29060
|
+
}, [
|
|
29061
|
+
state.step,
|
|
29062
|
+
state.extractSessionId,
|
|
29063
|
+
state.tokensPath,
|
|
29064
|
+
state.rawTokensPath,
|
|
29065
|
+
state.tokenGenerationStatus,
|
|
29066
|
+
state.selectionAgentStatus,
|
|
29067
|
+
state.compositionPhase,
|
|
29068
|
+
state.existingEntitiesStatus,
|
|
29069
|
+
state.existingEntitiesPath
|
|
29070
|
+
]);
|
|
28075
29071
|
const startGeneratePrefetch = (extractSessionId, tokensPath) => {
|
|
28076
29072
|
const args = buildGenerateArgs(extractSessionId, tokensPath);
|
|
28077
29073
|
let progressCursor = null;
|
|
@@ -28126,13 +29122,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28126
29122
|
});
|
|
28127
29123
|
return donePromise;
|
|
28128
29124
|
};
|
|
28129
|
-
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false) => {
|
|
29125
|
+
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false, cachedComponents = []) => {
|
|
28130
29126
|
const timer = startWizardTimer("component-generation", {
|
|
28131
29127
|
sessionId: extractSessionId,
|
|
28132
29128
|
acceptedCount,
|
|
28133
|
-
suppressScreen
|
|
29129
|
+
suppressScreen,
|
|
29130
|
+
noCache: effectiveNoCache
|
|
28134
29131
|
});
|
|
28135
|
-
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath);
|
|
29132
|
+
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath, cachedComponents);
|
|
28136
29133
|
let progressCursor = state.generateProgress;
|
|
28137
29134
|
const { donePromise } = spawnGenerateChild({
|
|
28138
29135
|
command: "node",
|
|
@@ -28202,6 +29199,25 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28202
29199
|
finishSelectionToReviewTimer("error");
|
|
28203
29200
|
}
|
|
28204
29201
|
};
|
|
29202
|
+
const finishCachedGeneration = async (sessionId2, acceptedCount) => {
|
|
29203
|
+
if (await runMapTokens2(sessionId2, true)) {
|
|
29204
|
+
finishSelectionToReviewTimer("cached");
|
|
29205
|
+
update(
|
|
29206
|
+
{
|
|
29207
|
+
acceptedCount,
|
|
29208
|
+
autoRejectedCount: 0,
|
|
29209
|
+
generateSessionId: sessionId2,
|
|
29210
|
+
generatedCount: acceptedCount,
|
|
29211
|
+
generateProgress: null,
|
|
29212
|
+
mapTokensStatus: "complete",
|
|
29213
|
+
step: "final-review"
|
|
29214
|
+
},
|
|
29215
|
+
{ clearScreen: false }
|
|
29216
|
+
);
|
|
29217
|
+
} else {
|
|
29218
|
+
finishSelectionToReviewTimer("error");
|
|
29219
|
+
}
|
|
29220
|
+
};
|
|
28205
29221
|
const advanceToPushFlow = (generatedAcceptedCount) => {
|
|
28206
29222
|
update({ generatedAcceptedCount });
|
|
28207
29223
|
void runSaveAndPush();
|
|
@@ -28386,8 +29402,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28386
29402
|
}
|
|
28387
29403
|
}
|
|
28388
29404
|
if (await runAgentAuthCheck("generating", true)) {
|
|
28389
|
-
|
|
28390
|
-
|
|
29405
|
+
const cacheHit = await checkGenerateCache(sid, state.tokensPath);
|
|
29406
|
+
if (cacheHit) {
|
|
29407
|
+
update({ step: "generating" });
|
|
29408
|
+
void finishCachedGeneration(sid, state.acceptedCount);
|
|
29409
|
+
} else {
|
|
29410
|
+
update({ step: "generating" });
|
|
29411
|
+
void runGenerate(sid, state.tokensPath, state.acceptedCount);
|
|
29412
|
+
}
|
|
28391
29413
|
}
|
|
28392
29414
|
return;
|
|
28393
29415
|
}
|
|
@@ -28751,7 +29773,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28751
29773
|
});
|
|
28752
29774
|
return { ok: false };
|
|
28753
29775
|
}
|
|
28754
|
-
await new Promise((
|
|
29776
|
+
await new Promise((resolve22) => setTimeout(resolve22, SAVE_CONFIRMATION_DELAY_MS));
|
|
28755
29777
|
update(nextStateAfterPrint({ skipGate: opts.skipGate, componentsPath }));
|
|
28756
29778
|
return { ok: true };
|
|
28757
29779
|
};
|
|
@@ -28828,6 +29850,12 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28828
29850
|
tokenReuseChecked.current = true;
|
|
28829
29851
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28830
29852
|
const existingTokensPath = join23(state.outDir, "tokens.json");
|
|
29853
|
+
if (effectiveNoCache) {
|
|
29854
|
+
tokenGenerationPromiseRef.current = runAgentAuthCheck(tokenNextStep).then(
|
|
29855
|
+
(ok2) => ok2 ? runGenerateTokens(state.rawTokensPath, state.outDir) : false
|
|
29856
|
+
);
|
|
29857
|
+
return;
|
|
29858
|
+
}
|
|
28831
29859
|
(async () => {
|
|
28832
29860
|
try {
|
|
28833
29861
|
await access7(existingTokensPath);
|
|
@@ -28911,7 +29939,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28911
29939
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28912
29940
|
update({ step: tokenNextStep });
|
|
28913
29941
|
if (await runAgentAuthCheck(tokenNextStep)) {
|
|
28914
|
-
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir);
|
|
29942
|
+
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir, true);
|
|
28915
29943
|
}
|
|
28916
29944
|
},
|
|
28917
29945
|
onQuit: () => process.exit(0)
|
|
@@ -28945,7 +29973,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28945
29973
|
);
|
|
28946
29974
|
case "extracting": {
|
|
28947
29975
|
const ep = state.extractProgress;
|
|
28948
|
-
const compositionComplete = state.compositionPhase === "done";
|
|
29976
|
+
const compositionComplete = state.compositionPhase === "done" || state.compositionPhase === "cache-hit";
|
|
28949
29977
|
const tokenGenerationComplete = !state.rawTokensPath || state.tokenGenerationStatus === "complete";
|
|
28950
29978
|
const extractionTasksComplete = ep !== null && ep.totalFiles > 0 && compositionComplete && state.selectionAgentStatus === "complete" && tokenGenerationComplete && state.existingEntitiesStatus !== "running";
|
|
28951
29979
|
if (extractionTasksComplete) return null;
|
|
@@ -28960,7 +29988,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28960
29988
|
extractDetail = "Scanning files...";
|
|
28961
29989
|
}
|
|
28962
29990
|
const selectionDetail = state.selectionAgentStatus === "complete" ? "Selection agent complete" : `Filtering component selection via ${state.agent}...`;
|
|
28963
|
-
const compositionDetail = compositionComplete ? "Composition mapping complete" : "Mapping composition
|
|
29991
|
+
const compositionDetail = state.compositionPhase === "cache-hit" ? "Composition mapping (cached)" : compositionComplete ? "Composition mapping complete" : state.compositionPhase?.startsWith("agent:") ? `Mapping composition via ${state.compositionPhase.slice("agent:".length)}...` : `Mapping composition via ${state.agent}...`;
|
|
28964
29992
|
return /* @__PURE__ */ jsx50(
|
|
28965
29993
|
RunningStep,
|
|
28966
29994
|
{
|
|
@@ -29010,6 +30038,29 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
29010
30038
|
acceptedCount: decisions.accepted.length,
|
|
29011
30039
|
rejectedCount: decisions.rejected.length
|
|
29012
30040
|
}) : null;
|
|
30041
|
+
const preflight = generationCachePreflightRef.current;
|
|
30042
|
+
const cachePromise = preflight?.sessionId === sessionId2 ? preflight.promise : checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
30043
|
+
if (!preflight || preflight.sessionId !== sessionId2) {
|
|
30044
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: cachePromise };
|
|
30045
|
+
}
|
|
30046
|
+
const cacheWaitStartedAt = startWizardTimer("selection-cache-restoration-wait", {
|
|
30047
|
+
sessionId: sessionId2,
|
|
30048
|
+
preflight: Boolean(preflight?.sessionId === sessionId2)
|
|
30049
|
+
});
|
|
30050
|
+
try {
|
|
30051
|
+
const cachedNames = await cachePromise;
|
|
30052
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30053
|
+
status: "complete",
|
|
30054
|
+
cachedCount: cachedNames.size
|
|
30055
|
+
});
|
|
30056
|
+
} catch (error) {
|
|
30057
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30058
|
+
status: "error",
|
|
30059
|
+
error: error instanceof Error ? error.message : String(error)
|
|
30060
|
+
});
|
|
30061
|
+
finishSelectionToReviewTimer("error");
|
|
30062
|
+
throw error;
|
|
30063
|
+
}
|
|
29013
30064
|
await runScopeGate({
|
|
29014
30065
|
sessionId: sessionId2,
|
|
29015
30066
|
decisions,
|
|
@@ -29018,12 +30069,35 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
29018
30069
|
if (shouldGenerateAfterScopeGate({ acceptedCount })) {
|
|
29019
30070
|
const authPromise = runAgentAuthCheck("generating", true);
|
|
29020
30071
|
if (await authPromise) {
|
|
29021
|
-
|
|
29022
|
-
|
|
29023
|
-
|
|
29024
|
-
acceptedCount
|
|
30072
|
+
const comparisonStartedAt = startWizardTimer("generation-cache-set-comparison", {
|
|
30073
|
+
sessionId: sid,
|
|
30074
|
+
acceptedCount: decisions?.accepted.length ?? 0
|
|
29025
30075
|
});
|
|
29026
|
-
|
|
30076
|
+
let cachedNames = await cachePromise;
|
|
30077
|
+
const acceptedNames = decisions?.accepted ?? [];
|
|
30078
|
+
let cacheHit = !effectiveNoCache && acceptedNames.length > 0 && acceptedNames.every((name) => cachedNames.has(name));
|
|
30079
|
+
if (!cacheHit && !effectiveNoCache && acceptedNames.length > 0) {
|
|
30080
|
+
cachedNames = await checkGenerateCacheComponents(sid, state.tokensPath, true);
|
|
30081
|
+
cacheHit = acceptedNames.every((name) => cachedNames.has(name));
|
|
30082
|
+
}
|
|
30083
|
+
finishWizardTimer("generation-cache-set-comparison", comparisonStartedAt, {
|
|
30084
|
+
status: "complete",
|
|
30085
|
+
cacheHit,
|
|
30086
|
+
cachedCount: cachedNames.size,
|
|
30087
|
+
acceptedCount: acceptedNames.length
|
|
30088
|
+
});
|
|
30089
|
+
if (cacheHit) {
|
|
30090
|
+
void finishCachedGeneration(sid, acceptedCount);
|
|
30091
|
+
} else {
|
|
30092
|
+
const acceptedNameSet = new Set(acceptedNames);
|
|
30093
|
+
const restoredCachedNames = [...cachedNames].filter((name) => acceptedNameSet.has(name));
|
|
30094
|
+
update({
|
|
30095
|
+
step: "generating",
|
|
30096
|
+
generateProgress: null,
|
|
30097
|
+
acceptedCount
|
|
30098
|
+
});
|
|
30099
|
+
void runGenerate(sid, state.tokensPath, acceptedCount, false, restoredCachedNames);
|
|
30100
|
+
}
|
|
29027
30101
|
} else {
|
|
29028
30102
|
finishSelectionToReviewTimer("error");
|
|
29029
30103
|
}
|
|
@@ -29389,7 +30463,7 @@ function registerImportCommand(program) {
|
|
|
29389
30463
|
"Override a composition, selection, token, generation, or token-mapping prompt (repeatable). value is a file path or literal text, e.g. --prompt select=./p.md",
|
|
29390
30464
|
(v, acc) => [...acc, v],
|
|
29391
30465
|
[]
|
|
29392
|
-
).action(async (opts) => {
|
|
30466
|
+
).option("--no-cache", "Re-run all steps even if output already exists").action(async (opts) => {
|
|
29393
30467
|
const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
|
|
29394
30468
|
if (opts.tokens !== void 0) {
|
|
29395
30469
|
const { access: access9 } = await import("node:fs/promises");
|
|
@@ -29426,6 +30500,7 @@ function registerImportCommand(program) {
|
|
|
29426
30500
|
...resolvedModel ? { initialModel: resolvedModel } : {},
|
|
29427
30501
|
initialProjectPath: opts.project !== "." ? normalizePath(opts.project) : void 0,
|
|
29428
30502
|
...buildCompositionForwardingOptions(opts),
|
|
30503
|
+
noCache: opts.cache === false,
|
|
29429
30504
|
skipMapTokens: false,
|
|
29430
30505
|
livePreview: true,
|
|
29431
30506
|
generatePromptPath: creds.generatePromptPath,
|
|
@@ -29513,7 +30588,7 @@ async function pathExists3(path) {
|
|
|
29513
30588
|
return access8(path).then(() => true).catch(() => false);
|
|
29514
30589
|
}
|
|
29515
30590
|
function runSpawn(cmd, args, opts = {}) {
|
|
29516
|
-
return new Promise((
|
|
30591
|
+
return new Promise((resolve22) => {
|
|
29517
30592
|
const child = spawn6(cmd, args, {
|
|
29518
30593
|
cwd: opts.cwd,
|
|
29519
30594
|
env: opts.env ?? process.env,
|
|
@@ -29525,7 +30600,7 @@ function runSpawn(cmd, args, opts = {}) {
|
|
|
29525
30600
|
const settle = (result) => {
|
|
29526
30601
|
if (settled) return;
|
|
29527
30602
|
settled = true;
|
|
29528
|
-
|
|
30603
|
+
resolve22(result);
|
|
29529
30604
|
};
|
|
29530
30605
|
child.on("error", (err) => settle({ exitCode: 1, stdout: "", stderr: err.message }));
|
|
29531
30606
|
child.stdout.on("data", (d) => {
|
|
@@ -30726,13 +31801,13 @@ function PrerequisitesScreen({
|
|
|
30726
31801
|
const driver = {
|
|
30727
31802
|
...base,
|
|
30728
31803
|
emit: (event) => setEvents((current) => [...current, event]),
|
|
30729
|
-
confirm: (question, defaultYes = true) => new Promise((
|
|
31804
|
+
confirm: (question, defaultYes = true) => new Promise((resolve22) => {
|
|
30730
31805
|
setConfirm({
|
|
30731
31806
|
question,
|
|
30732
31807
|
defaultYes,
|
|
30733
31808
|
resolve: (answer) => {
|
|
30734
31809
|
setConfirm(null);
|
|
30735
|
-
|
|
31810
|
+
resolve22(answer);
|
|
30736
31811
|
}
|
|
30737
31812
|
});
|
|
30738
31813
|
})
|
|
@@ -30807,8 +31882,8 @@ function SetupScreen({
|
|
|
30807
31882
|
useEffect21(() => {
|
|
30808
31883
|
if (startedRef.current) return;
|
|
30809
31884
|
startedRef.current = true;
|
|
30810
|
-
const runScreen = (build) => new Promise((
|
|
30811
|
-
setScreen(build(
|
|
31885
|
+
const runScreen = (build) => new Promise((resolve22) => {
|
|
31886
|
+
setScreen(build(resolve22));
|
|
30812
31887
|
});
|
|
30813
31888
|
void (async () => {
|
|
30814
31889
|
const results = [];
|
|
@@ -30986,9 +32061,9 @@ var init_command8 = __esm({
|
|
|
30986
32061
|
function rank(p) {
|
|
30987
32062
|
if (p === "typed-slot") return 1;
|
|
30988
32063
|
if (p === "structural") return 2;
|
|
30989
|
-
if (p === "
|
|
30990
|
-
if (p === "
|
|
30991
|
-
if (p
|
|
32064
|
+
if (p === "manifest") return 3;
|
|
32065
|
+
if (p === "doc") return 4;
|
|
32066
|
+
if (p.startsWith("adapter:")) return 5;
|
|
30992
32067
|
return 6;
|
|
30993
32068
|
}
|
|
30994
32069
|
function mergeEdges(all) {
|
|
@@ -31024,6 +32099,65 @@ var init_merge_edges = __esm({
|
|
|
31024
32099
|
}
|
|
31025
32100
|
});
|
|
31026
32101
|
|
|
32102
|
+
// packages/experience-design-system-cli-legacy/src/analyze/composition/parse-map-edges.ts
|
|
32103
|
+
function parseMapEdges(raw, opts) {
|
|
32104
|
+
const edges = [];
|
|
32105
|
+
const warnings = [];
|
|
32106
|
+
const { componentNames } = opts;
|
|
32107
|
+
for (const line of raw.split("\n")) {
|
|
32108
|
+
const trimmed = line.trim();
|
|
32109
|
+
if (!trimmed.startsWith("{")) continue;
|
|
32110
|
+
let obj;
|
|
32111
|
+
try {
|
|
32112
|
+
obj = JSON.parse(trimmed);
|
|
32113
|
+
} catch {
|
|
32114
|
+
warnings.push(`unparseable line: ${trimmed.slice(0, 120)}`);
|
|
32115
|
+
continue;
|
|
32116
|
+
}
|
|
32117
|
+
if (typeof obj !== "object" || obj === null || !("tool" in obj)) continue;
|
|
32118
|
+
const rec = obj;
|
|
32119
|
+
if (!VALID_MAP_TOOL_NAMES.has(rec.tool)) {
|
|
32120
|
+
warnings.push(`unknown tool: ${String(rec.tool)}`);
|
|
32121
|
+
continue;
|
|
32122
|
+
}
|
|
32123
|
+
if (typeof rec.parent !== "string" || !rec.parent || typeof rec.child !== "string" || !rec.child) {
|
|
32124
|
+
warnings.push("map_edge missing parent/child \u2014 skipped");
|
|
32125
|
+
continue;
|
|
32126
|
+
}
|
|
32127
|
+
const { parent, child } = rec;
|
|
32128
|
+
if (!componentNames.has(parent)) {
|
|
32129
|
+
warnings.push(`map_edge names unknown component (parent): ${parent} \u2014 skipped`);
|
|
32130
|
+
continue;
|
|
32131
|
+
}
|
|
32132
|
+
if (!componentNames.has(child)) {
|
|
32133
|
+
warnings.push(`map_edge names unknown component (child): ${child} \u2014 skipped`);
|
|
32134
|
+
continue;
|
|
32135
|
+
}
|
|
32136
|
+
const edge = { parent, child, provenance: "agent" };
|
|
32137
|
+
if (typeof rec.slot === "string" && rec.slot) {
|
|
32138
|
+
edge.slot = rec.slot;
|
|
32139
|
+
}
|
|
32140
|
+
if (rec.confidence !== void 0) {
|
|
32141
|
+
if (typeof rec.confidence === "number" && rec.confidence >= 1 && rec.confidence <= 5) {
|
|
32142
|
+
edge.confidence = rec.confidence;
|
|
32143
|
+
} else {
|
|
32144
|
+
warnings.push(
|
|
32145
|
+
`map_edge (${parent}\u2192${child}): invalid confidence ${String(rec.confidence)} \u2014 edge kept without confidence`
|
|
32146
|
+
);
|
|
32147
|
+
}
|
|
32148
|
+
}
|
|
32149
|
+
edges.push(edge);
|
|
32150
|
+
}
|
|
32151
|
+
return { edges, warnings };
|
|
32152
|
+
}
|
|
32153
|
+
var VALID_MAP_TOOL_NAMES;
|
|
32154
|
+
var init_parse_map_edges = __esm({
|
|
32155
|
+
"packages/experience-design-system-cli-legacy/src/analyze/composition/parse-map-edges.ts"() {
|
|
32156
|
+
"use strict";
|
|
32157
|
+
VALID_MAP_TOOL_NAMES = /* @__PURE__ */ new Set(["map_edge"]);
|
|
32158
|
+
}
|
|
32159
|
+
});
|
|
32160
|
+
|
|
31027
32161
|
// packages/experience-design-system-cli-legacy/src/analyze/composition/apply-mapping.ts
|
|
31028
32162
|
function applyMapping(components, edges) {
|
|
31029
32163
|
const warnings = [];
|
|
@@ -31083,9 +32217,44 @@ var init_apply_mapping = __esm({
|
|
|
31083
32217
|
}
|
|
31084
32218
|
});
|
|
31085
32219
|
|
|
32220
|
+
// packages/experience-design-system-cli-legacy/src/analyze/composition/prompt-loader.ts
|
|
32221
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
32222
|
+
import { dirname as dirname17, join as join27, resolve as resolve19 } from "node:path";
|
|
32223
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
32224
|
+
function resolvePromptPath(fileName) {
|
|
32225
|
+
const thisDir = dirname17(fileURLToPath3(import.meta.url));
|
|
32226
|
+
let dir = thisDir;
|
|
32227
|
+
for (; ; ) {
|
|
32228
|
+
const candidate = join27(dir, "prompts");
|
|
32229
|
+
if (existsSync10(candidate)) return join27(candidate, fileName);
|
|
32230
|
+
const parent = resolve19(dir, "..");
|
|
32231
|
+
if (parent === dir) {
|
|
32232
|
+
throw new Error(
|
|
32233
|
+
`prompt file missing from CLI installation (could not locate prompts/ directory from: ${thisDir})`
|
|
32234
|
+
);
|
|
32235
|
+
}
|
|
32236
|
+
dir = parent;
|
|
32237
|
+
}
|
|
32238
|
+
}
|
|
32239
|
+
function loadPrompt(fileName) {
|
|
32240
|
+
const path = resolvePromptPath(fileName);
|
|
32241
|
+
try {
|
|
32242
|
+
return readFileSync10(path, "utf8");
|
|
32243
|
+
} catch {
|
|
32244
|
+
throw new Error(`prompt file missing from CLI installation \u2014 try reinstalling the CLI (looked for: ${path})`);
|
|
32245
|
+
}
|
|
32246
|
+
}
|
|
32247
|
+
var init_prompt_loader = __esm({
|
|
32248
|
+
"packages/experience-design-system-cli-legacy/src/analyze/composition/prompt-loader.ts"() {
|
|
32249
|
+
"use strict";
|
|
32250
|
+
}
|
|
32251
|
+
});
|
|
32252
|
+
|
|
31086
32253
|
// packages/experience-design-system-cli-legacy/src/analyze/composition/resolve-mapping.ts
|
|
31087
|
-
function resolveMapping(input) {
|
|
32254
|
+
async function resolveMapping(input) {
|
|
32255
|
+
const componentNames = new Set(input.components.map((c2) => c2.name));
|
|
31088
32256
|
const collected = [];
|
|
32257
|
+
const agentWarnings = [];
|
|
31089
32258
|
for (const c2 of input.components) {
|
|
31090
32259
|
for (const slot of c2.slots) {
|
|
31091
32260
|
for (const child of slot.allowedComponents ?? []) {
|
|
@@ -31103,41 +32272,17 @@ function resolveMapping(input) {
|
|
|
31103
32272
|
if (input.extraEdges) {
|
|
31104
32273
|
collected.push(...input.extraEdges);
|
|
31105
32274
|
}
|
|
31106
|
-
for (const evidence of input.sourceCallSiteEvidence ?? []) {
|
|
31107
|
-
collected.push({
|
|
31108
|
-
parent: evidence.parent,
|
|
31109
|
-
child: evidence.child,
|
|
31110
|
-
...evidence.slot ? { slot: evidence.slot } : {},
|
|
31111
|
-
citation: { sourcePath: evidence.sourcePath, startLine: evidence.startLine, endLine: evidence.endLine },
|
|
31112
|
-
provenance: "call-site"
|
|
31113
|
-
});
|
|
31114
|
-
}
|
|
31115
32275
|
const coveredParents = new Set(collected.map((e) => e.parent));
|
|
31116
32276
|
const residueParents = input.components.map((c2) => c2.name).filter((n) => !coveredParents.has(n));
|
|
31117
|
-
const
|
|
31118
|
-
|
|
31119
|
-
const
|
|
31120
|
-
|
|
31121
|
-
|
|
31122
|
-
|
|
31123
|
-
|
|
31124
|
-
|
|
31125
|
-
coveredParents: [...coveredParents].sort(),
|
|
31126
|
-
residueParents,
|
|
31127
|
-
sourceCallSiteAccepted: input.sourceCallSiteEvidence?.length ?? 0,
|
|
31128
|
-
sourceCallSiteRejected: input.sourceCallSiteRejections?.length ?? 0
|
|
31129
|
-
});
|
|
32277
|
+
const shouldRunAgent = input.forceAgent || residueParents.length > 0 && input.files.length > 0;
|
|
32278
|
+
if (shouldRunAgent) {
|
|
32279
|
+
const prompt = input.buildPrompt ? input.buildPrompt(input.files, [...componentNames]) : defaultPrompt(input.files, [...componentNames], input.promptOverride);
|
|
32280
|
+
const raw = await input.runAgentFn({ prompt, files: input.files }) ?? "";
|
|
32281
|
+
const parsed = parseMapEdges(raw, { componentNames });
|
|
32282
|
+
collected.push(...parsed.edges);
|
|
32283
|
+
agentWarnings.push(...parsed.warnings);
|
|
32284
|
+
}
|
|
31130
32285
|
const merged = mergeEdges(collected);
|
|
31131
|
-
debug.event("analyze", "composition.merged", {
|
|
31132
|
-
edgeCountsByProvenance: countByProvenance(merged.edges),
|
|
31133
|
-
conflicts: merged.conflicts,
|
|
31134
|
-
edges: merged.edges.map((edge) => ({
|
|
31135
|
-
parent: edge.parent,
|
|
31136
|
-
child: edge.child,
|
|
31137
|
-
slot: edge.slot ?? null,
|
|
31138
|
-
provenance: edge.provenance
|
|
31139
|
-
}))
|
|
31140
|
-
});
|
|
31141
32286
|
const base = input.components.map((c2) => ({
|
|
31142
32287
|
...c2,
|
|
31143
32288
|
slots: c2.slots.map((s) => {
|
|
@@ -31146,32 +32291,127 @@ function resolveMapping(input) {
|
|
|
31146
32291
|
})
|
|
31147
32292
|
}));
|
|
31148
32293
|
const applied = applyMapping(base, merged.edges);
|
|
31149
|
-
debug.event("analyze", "composition.applied", {
|
|
31150
|
-
slots: applied.components.flatMap(
|
|
31151
|
-
(component) => component.slots.filter((slot) => (slot.allowedComponents?.length ?? 0) > 0).map((slot) => ({ component: component.name, slot: slot.name, allowedComponents: slot.allowedComponents }))
|
|
31152
|
-
),
|
|
31153
|
-
warnings: applied.warnings
|
|
31154
|
-
});
|
|
31155
32294
|
return {
|
|
31156
32295
|
components: applied.components,
|
|
31157
32296
|
edges: merged.edges,
|
|
31158
32297
|
conflicts: merged.conflicts,
|
|
31159
|
-
warnings: applied.warnings
|
|
31160
|
-
sourceCallSiteEvidence: [...input.sourceCallSiteEvidence ?? []],
|
|
31161
|
-
sourceCallSiteRejections: [...input.sourceCallSiteRejections ?? []]
|
|
32298
|
+
warnings: [...agentWarnings, ...applied.warnings]
|
|
31162
32299
|
};
|
|
31163
32300
|
}
|
|
32301
|
+
function defaultPrompt(files, componentNames, promptOverride) {
|
|
32302
|
+
const fileBlocks = files.map((f) => `--- ${f.path} ---
|
|
32303
|
+
${f.content}`).join("\n\n");
|
|
32304
|
+
const instruction = promptOverride?.trim() ? promptOverride.trim() : loadPrompt("composition-edges.md").trim();
|
|
32305
|
+
return [
|
|
32306
|
+
instruction,
|
|
32307
|
+
"",
|
|
32308
|
+
'Emit one JSON object per line, each: {"tool":"map_edge","parent":"<Name>","child":"<Name>","slot"?:"<slot>","confidence"?:1-5,"reason":"<cite the file + declaration>"}.',
|
|
32309
|
+
"Use ONLY these exact component names (an edge naming anything else is dropped):",
|
|
32310
|
+
componentNames.join(", "),
|
|
32311
|
+
"",
|
|
32312
|
+
"Candidate files:",
|
|
32313
|
+
fileBlocks
|
|
32314
|
+
].join("\n");
|
|
32315
|
+
}
|
|
31164
32316
|
var init_resolve_mapping = __esm({
|
|
31165
32317
|
"packages/experience-design-system-cli-legacy/src/analyze/composition/resolve-mapping.ts"() {
|
|
31166
32318
|
"use strict";
|
|
31167
32319
|
init_merge_edges();
|
|
32320
|
+
init_parse_map_edges();
|
|
31168
32321
|
init_apply_mapping();
|
|
31169
|
-
|
|
32322
|
+
init_prompt_loader();
|
|
32323
|
+
}
|
|
32324
|
+
});
|
|
32325
|
+
|
|
32326
|
+
// packages/experience-design-system-cli-legacy/src/analyze/composition/resolve-mapping-cli.ts
|
|
32327
|
+
function resolveCompositionSources(opts) {
|
|
32328
|
+
return {
|
|
32329
|
+
forceAgent: opts.compositionRefresh === true || opts.noCache === true
|
|
32330
|
+
};
|
|
32331
|
+
}
|
|
32332
|
+
var init_resolve_mapping_cli = __esm({
|
|
32333
|
+
"packages/experience-design-system-cli-legacy/src/analyze/composition/resolve-mapping-cli.ts"() {
|
|
32334
|
+
"use strict";
|
|
32335
|
+
}
|
|
32336
|
+
});
|
|
32337
|
+
|
|
32338
|
+
// packages/experience-design-system-cli-legacy/src/analyze/composition/candidate-files.ts
|
|
32339
|
+
function matchReason(file) {
|
|
32340
|
+
const segments = file.path.split("/").filter((s) => s !== "");
|
|
32341
|
+
for (const pattern of CANDIDATE_NAME_PATTERNS) {
|
|
32342
|
+
if (segments.some((seg) => pattern.test(seg))) {
|
|
32343
|
+
return `name:${pattern.source.toLowerCase()}`;
|
|
32344
|
+
}
|
|
32345
|
+
}
|
|
32346
|
+
for (const marker of CANDIDATE_CONTENT_MARKERS) {
|
|
32347
|
+
if (file.content.includes(marker)) return `content:${marker}`;
|
|
32348
|
+
}
|
|
32349
|
+
return void 0;
|
|
32350
|
+
}
|
|
32351
|
+
function selectCandidateFiles(files) {
|
|
32352
|
+
const selected = [];
|
|
32353
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32354
|
+
for (const file of files) {
|
|
32355
|
+
if (seen.has(file.path)) continue;
|
|
32356
|
+
const reason = matchReason(file);
|
|
32357
|
+
if (reason === void 0) continue;
|
|
32358
|
+
seen.add(file.path);
|
|
32359
|
+
selected.push({ path: file.path, content: file.content, reason });
|
|
32360
|
+
}
|
|
32361
|
+
return selected;
|
|
32362
|
+
}
|
|
32363
|
+
function capCandidatesToPromptBudget(files, budget = PROMPT_CANDIDATE_TOKEN_BUDGET) {
|
|
32364
|
+
const ordered = [...files].sort((a, b) => a.content.length - b.content.length || a.path.localeCompare(b.path));
|
|
32365
|
+
const kept = [];
|
|
32366
|
+
const dropped = [];
|
|
32367
|
+
let spent = 0;
|
|
32368
|
+
for (const file of ordered) {
|
|
32369
|
+
const cost = tokenCost(file);
|
|
32370
|
+
if (spent + cost > budget) {
|
|
32371
|
+
dropped.push(file);
|
|
32372
|
+
continue;
|
|
32373
|
+
}
|
|
32374
|
+
kept.push(file);
|
|
32375
|
+
spent += cost;
|
|
32376
|
+
}
|
|
32377
|
+
return { kept, dropped };
|
|
32378
|
+
}
|
|
32379
|
+
function tokenCost(file) {
|
|
32380
|
+
return Math.ceil(file.content.length / CHARS_PER_TOKEN);
|
|
32381
|
+
}
|
|
32382
|
+
var CANDIDATE_NAME_PATTERNS, CANDIDATE_CONTENT_MARKERS, PROMPT_CANDIDATE_TOKEN_BUDGET, CHARS_PER_TOKEN;
|
|
32383
|
+
var init_candidate_files = __esm({
|
|
32384
|
+
"packages/experience-design-system-cli-legacy/src/analyze/composition/candidate-files.ts"() {
|
|
32385
|
+
"use strict";
|
|
32386
|
+
CANDIDATE_NAME_PATTERNS = [/mapping/i, /meta/i, /registry/i, /schema/i, /composition/i];
|
|
32387
|
+
CANDIDATE_CONTENT_MARKERS = [
|
|
32388
|
+
"requiredParent",
|
|
32389
|
+
"withParentType",
|
|
32390
|
+
"allowedTagNames",
|
|
32391
|
+
"createContext",
|
|
32392
|
+
"MappingContext",
|
|
32393
|
+
"allowedComponents"
|
|
32394
|
+
];
|
|
32395
|
+
PROMPT_CANDIDATE_TOKEN_BUDGET = 8e4;
|
|
32396
|
+
CHARS_PER_TOKEN = 4;
|
|
32397
|
+
}
|
|
32398
|
+
});
|
|
32399
|
+
|
|
32400
|
+
// packages/experience-design-system-cli-legacy/src/analyze/composition/composition-cache-key.ts
|
|
32401
|
+
function buildCompositionInputHash(input) {
|
|
32402
|
+
const fileDigest = input.files.map((f) => `${f.path} ${hashContent(f.content)}`).sort().join("");
|
|
32403
|
+
return hashContent(`agent:${input.agent}
|
|
32404
|
+
${fileDigest}`);
|
|
32405
|
+
}
|
|
32406
|
+
var init_composition_cache_key = __esm({
|
|
32407
|
+
"packages/experience-design-system-cli-legacy/src/analyze/composition/composition-cache-key.ts"() {
|
|
32408
|
+
"use strict";
|
|
32409
|
+
init_cache_keys();
|
|
31170
32410
|
}
|
|
31171
32411
|
});
|
|
31172
32412
|
|
|
31173
32413
|
// packages/experience-design-system-cli-legacy/src/analyze/composition/manifest-doc-evidence.ts
|
|
31174
|
-
import { dirname as
|
|
32414
|
+
import { dirname as dirname18 } from "node:path";
|
|
31175
32415
|
function kebabToPascal2(name) {
|
|
31176
32416
|
return name.split("-").filter(Boolean).map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1)).join("");
|
|
31177
32417
|
}
|
|
@@ -31221,8 +32461,8 @@ function collectAgentsDocEdges(files, components, componentNames) {
|
|
|
31221
32461
|
const seen = /* @__PURE__ */ new Set();
|
|
31222
32462
|
for (const file of files) {
|
|
31223
32463
|
if (!file.path.endsWith("AGENTS.md")) continue;
|
|
31224
|
-
const docDir =
|
|
31225
|
-
const parent = components.find((c2) => c2.sourcePath &&
|
|
32464
|
+
const docDir = dirname18(file.path);
|
|
32465
|
+
const parent = components.find((c2) => c2.sourcePath && dirname18(c2.sourcePath) === docDir)?.name;
|
|
31226
32466
|
if (!parent || !componentNames.has(parent)) continue;
|
|
31227
32467
|
for (const line of file.content.split("\n")) {
|
|
31228
32468
|
const lower = line.toLowerCase();
|
|
@@ -31252,172 +32492,12 @@ var init_manifest_doc_evidence = __esm({
|
|
|
31252
32492
|
}
|
|
31253
32493
|
});
|
|
31254
32494
|
|
|
31255
|
-
// packages/experience-design-system-cli-legacy/src/analyze/composition/source-call-site-evidence.ts
|
|
31256
|
-
import { Node as Node49, Project as Project11, SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
31257
|
-
function collectSourceCallSiteEvidence(files, components) {
|
|
31258
|
-
const componentNames = new Set(components.map((component) => component.name));
|
|
31259
|
-
const componentsBySource = /* @__PURE__ */ new Map();
|
|
31260
|
-
for (const component of components) {
|
|
31261
|
-
const sourcePath = component.sourcePath ?? component.source;
|
|
31262
|
-
const siblings = componentsBySource.get(sourcePath) ?? [];
|
|
31263
|
-
siblings.push(component);
|
|
31264
|
-
componentsBySource.set(sourcePath, siblings);
|
|
31265
|
-
}
|
|
31266
|
-
const project = new Project11({
|
|
31267
|
-
compilerOptions: { jsx: 1, target: 99, module: 99, moduleResolution: 100, skipLibCheck: true, allowJs: true },
|
|
31268
|
-
skipAddingFilesFromTsConfig: true
|
|
31269
|
-
});
|
|
31270
|
-
const sourceFiles = new Map(
|
|
31271
|
-
files.map((file) => [file.path, project.createSourceFile(file.path, file.content, { overwrite: true })])
|
|
31272
|
-
);
|
|
31273
|
-
const accepted = [];
|
|
31274
|
-
const rejected = [];
|
|
31275
|
-
for (const [sourcePath, parents] of componentsBySource) {
|
|
31276
|
-
const sourceFile = sourceFiles.get(sourcePath);
|
|
31277
|
-
if (!sourceFile) continue;
|
|
31278
|
-
const boundNames = collectBoundNames(sourceFile);
|
|
31279
|
-
for (const parent of parents) {
|
|
31280
|
-
for (const jsxElement of [
|
|
31281
|
-
...sourceFile.getDescendantsOfKind(SyntaxKind15.JsxSelfClosingElement),
|
|
31282
|
-
...sourceFile.getDescendantsOfKind(SyntaxKind15.JsxElement)
|
|
31283
|
-
]) {
|
|
31284
|
-
const tagName = Node49.isJsxSelfClosingElement(jsxElement) ? jsxElement.getTagNameNode().getText() : jsxElement.getOpeningElement().getTagNameNode().getText();
|
|
31285
|
-
const candidate = tagName.split(".").at(-1) ?? tagName;
|
|
31286
|
-
if (candidate === parent.name || isIntrinsicTag(candidate)) continue;
|
|
31287
|
-
const lines = sourceExcerpt(sourceFile, jsxElement);
|
|
31288
|
-
if (!componentNames.has(candidate)) {
|
|
31289
|
-
rejected.push({ parent: parent.name, candidate, ...lines, reason: "unknown-component" });
|
|
31290
|
-
continue;
|
|
31291
|
-
}
|
|
31292
|
-
if (!boundNames.has(tagName) && !boundNames.has(candidate)) {
|
|
31293
|
-
rejected.push({ parent: parent.name, candidate, ...lines, reason: "unbound-component" });
|
|
31294
|
-
continue;
|
|
31295
|
-
}
|
|
31296
|
-
accepted.push({ parent: parent.name, child: candidate, ...lines, kind: "jsx-render" });
|
|
31297
|
-
}
|
|
31298
|
-
}
|
|
31299
|
-
}
|
|
31300
|
-
for (const sourceFile of sourceFiles.values()) {
|
|
31301
|
-
collectCallerSlotEvidence(sourceFile, componentNames, collectBoundNames(sourceFile), accepted, rejected);
|
|
31302
|
-
}
|
|
31303
|
-
const verifiedPairs = new Set(accepted.map((evidence) => `${evidence.parent}\0${evidence.child}`));
|
|
31304
|
-
for (const component of components) {
|
|
31305
|
-
const candidates = component.slots.flatMap((slot) => [
|
|
31306
|
-
...slot.allowedComponents ?? [],
|
|
31307
|
-
...slot.structuralAllowedComponents ?? []
|
|
31308
|
-
]);
|
|
31309
|
-
for (const candidate of candidates) {
|
|
31310
|
-
if (verifiedPairs.has(`${component.name}\0${candidate}`)) continue;
|
|
31311
|
-
rejected.push({
|
|
31312
|
-
parent: component.name,
|
|
31313
|
-
candidate,
|
|
31314
|
-
sourcePath: component.sourcePath ?? component.source,
|
|
31315
|
-
reason: "no-call-site"
|
|
31316
|
-
});
|
|
31317
|
-
}
|
|
31318
|
-
}
|
|
31319
|
-
return {
|
|
31320
|
-
accepted: dedupeEvidence(accepted),
|
|
31321
|
-
rejected: dedupeRejections(rejected)
|
|
31322
|
-
};
|
|
31323
|
-
}
|
|
31324
|
-
function collectCallerSlotEvidence(sourceFile, componentNames, boundNames, accepted, rejected) {
|
|
31325
|
-
for (const parentElement of sourceFile.getDescendantsOfKind(SyntaxKind15.JsxElement)) {
|
|
31326
|
-
const parentTag = parentElement.getOpeningElement().getTagNameNode().getText();
|
|
31327
|
-
const parent = parentTag.split(".").at(-1) ?? parentTag;
|
|
31328
|
-
if (!componentNames.has(parent) || !boundNames.has(parentTag)) continue;
|
|
31329
|
-
for (const childNode of parentElement.getJsxChildren()) {
|
|
31330
|
-
if (!Node49.isJsxElement(childNode) && !Node49.isJsxSelfClosingElement(childNode)) {
|
|
31331
|
-
if (Node49.isJsxText(childNode) && childNode.getText().trim()) {
|
|
31332
|
-
const lines2 = sourceExcerpt(sourceFile, childNode);
|
|
31333
|
-
rejected.push({ parent, candidate: "<text>", ...lines2, reason: "text-only-child" });
|
|
31334
|
-
}
|
|
31335
|
-
continue;
|
|
31336
|
-
}
|
|
31337
|
-
const childTag = Node49.isJsxElement(childNode) ? childNode.getOpeningElement().getTagNameNode().getText() : childNode.getTagNameNode().getText();
|
|
31338
|
-
const child = childTag.split(".").at(-1) ?? childTag;
|
|
31339
|
-
if (isIntrinsicTag(child)) continue;
|
|
31340
|
-
const lines = sourceExcerpt(sourceFile, childNode);
|
|
31341
|
-
if (!componentNames.has(child)) {
|
|
31342
|
-
rejected.push({ parent, candidate: child, ...lines, reason: "unknown-component" });
|
|
31343
|
-
continue;
|
|
31344
|
-
}
|
|
31345
|
-
if (!boundNames.has(childTag) && !boundNames.has(child)) {
|
|
31346
|
-
rejected.push({ parent, candidate: child, ...lines, reason: "unbound-component" });
|
|
31347
|
-
continue;
|
|
31348
|
-
}
|
|
31349
|
-
const slotAttribute = Node49.isJsxElement(childNode) ? childNode.getOpeningElement().getAttribute("slot") : childNode.getAttribute("slot");
|
|
31350
|
-
const slotValue = slotAttribute && Node49.isJsxAttribute(slotAttribute) ? slotAttribute.getInitializer() : void 0;
|
|
31351
|
-
const slot = slotValue && Node49.isStringLiteral(slotValue) ? slotValue.getLiteralValue() : void 0;
|
|
31352
|
-
accepted.push({ parent, child, ...slot ? { slot } : {}, ...lines, kind: "jsx-render" });
|
|
31353
|
-
}
|
|
31354
|
-
}
|
|
31355
|
-
}
|
|
31356
|
-
function collectBoundNames(sourceFile) {
|
|
31357
|
-
const names = /* @__PURE__ */ new Set();
|
|
31358
|
-
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
31359
|
-
const defaultImport = declaration.getDefaultImport();
|
|
31360
|
-
if (defaultImport) names.add(defaultImport.getText());
|
|
31361
|
-
const namespaceImport = declaration.getNamespaceImport();
|
|
31362
|
-
if (namespaceImport) names.add(namespaceImport.getText());
|
|
31363
|
-
for (const namedImport of declaration.getNamedImports()) {
|
|
31364
|
-
names.add((namedImport.getAliasNode() ?? namedImport.getNameNode()).getText());
|
|
31365
|
-
}
|
|
31366
|
-
}
|
|
31367
|
-
for (const declaration of sourceFile.getVariableDeclarations()) names.add(declaration.getName());
|
|
31368
|
-
for (const declaration of sourceFile.getFunctions()) {
|
|
31369
|
-
if (declaration.getName()) names.add(declaration.getName());
|
|
31370
|
-
}
|
|
31371
|
-
for (const declaration of sourceFile.getClasses()) {
|
|
31372
|
-
if (declaration.getName()) names.add(declaration.getName());
|
|
31373
|
-
}
|
|
31374
|
-
return names;
|
|
31375
|
-
}
|
|
31376
|
-
function sourceExcerpt(sourceFile, node) {
|
|
31377
|
-
const startLine = node.getStartLineNumber();
|
|
31378
|
-
const endLine = node.getEndLineNumber();
|
|
31379
|
-
const lines = sourceFile.getFullText().split("\n");
|
|
31380
|
-
return {
|
|
31381
|
-
sourcePath: sourceFile.getFilePath(),
|
|
31382
|
-
startLine,
|
|
31383
|
-
endLine,
|
|
31384
|
-
excerpt: lines.slice(startLine - 1, endLine).join("\n").trim()
|
|
31385
|
-
};
|
|
31386
|
-
}
|
|
31387
|
-
function isIntrinsicTag(tagName) {
|
|
31388
|
-
return /^[a-z]/.test(tagName) || tagName.includes("-");
|
|
31389
|
-
}
|
|
31390
|
-
function dedupeEvidence(evidence) {
|
|
31391
|
-
const seen = /* @__PURE__ */ new Set();
|
|
31392
|
-
return evidence.filter((item) => {
|
|
31393
|
-
const key = `${item.parent}\0${item.child}\0${item.slot ?? ""}\0${item.sourcePath}\0${item.startLine}`;
|
|
31394
|
-
if (seen.has(key)) return false;
|
|
31395
|
-
seen.add(key);
|
|
31396
|
-
return true;
|
|
31397
|
-
}).sort(
|
|
31398
|
-
(left, right) => `${left.parent}\0${left.child}\0${left.sourcePath}\0${left.startLine}`.localeCompare(
|
|
31399
|
-
`${right.parent}\0${right.child}\0${right.sourcePath}\0${right.startLine}`
|
|
31400
|
-
)
|
|
31401
|
-
);
|
|
31402
|
-
}
|
|
31403
|
-
function dedupeRejections(rejections) {
|
|
31404
|
-
const seen = /* @__PURE__ */ new Set();
|
|
31405
|
-
return rejections.filter((item) => {
|
|
31406
|
-
const key = `${item.parent}\0${item.candidate}\0${item.sourcePath}\0${item.startLine}`;
|
|
31407
|
-
if (seen.has(key)) return false;
|
|
31408
|
-
seen.add(key);
|
|
31409
|
-
return true;
|
|
31410
|
-
});
|
|
31411
|
-
}
|
|
31412
|
-
var init_source_call_site_evidence = __esm({
|
|
31413
|
-
"packages/experience-design-system-cli-legacy/src/analyze/composition/source-call-site-evidence.ts"() {
|
|
31414
|
-
"use strict";
|
|
31415
|
-
}
|
|
31416
|
-
});
|
|
31417
|
-
|
|
31418
32495
|
// packages/experience-design-system-cli-legacy/src/analyze/extract-command.ts
|
|
31419
|
-
import { mkdir as mkdir6, readdir as readdir3, readFile as
|
|
31420
|
-
import { isAbsolute as isAbsolute2, join as
|
|
32496
|
+
import { mkdir as mkdir6, readdir as readdir3, readFile as readFile19, stat as stat6 } from "node:fs/promises";
|
|
32497
|
+
import { isAbsolute as isAbsolute2, join as join28, relative as relative2, resolve as resolve20 } from "node:path";
|
|
32498
|
+
function resolveExtractNoCache(opts) {
|
|
32499
|
+
return opts.noCache === true || opts.cache === false;
|
|
32500
|
+
}
|
|
31421
32501
|
function isDenylistedNoiseFile(name) {
|
|
31422
32502
|
return DENYLISTED_EXACT_FILE_NAMES.has(name) || DENYLISTED_FILE_NAME_PATTERNS.some((pattern) => pattern.test(name));
|
|
31423
32503
|
}
|
|
@@ -31431,12 +32511,12 @@ async function retryDatabaseWrite(operation, attempts = 8) {
|
|
|
31431
32511
|
} catch (error) {
|
|
31432
32512
|
const message = error instanceof Error ? error.message : String(error);
|
|
31433
32513
|
if (!/database is locked|database is busy/i.test(message) || attempt >= attempts) throw error;
|
|
31434
|
-
await new Promise((
|
|
32514
|
+
await new Promise((resolve22) => setTimeout(resolve22, Math.min(250 * attempt, 2e3)));
|
|
31435
32515
|
}
|
|
31436
32516
|
}
|
|
31437
32517
|
}
|
|
31438
32518
|
function resolveFromProjectRoot(projectRoot, inputPath) {
|
|
31439
|
-
return isAbsolute2(inputPath) ? inputPath :
|
|
32519
|
+
return isAbsolute2(inputPath) ? inputPath : resolve20(projectRoot, inputPath);
|
|
31440
32520
|
}
|
|
31441
32521
|
async function pathExists4(path) {
|
|
31442
32522
|
return Boolean(await stat6(path).catch(() => null));
|
|
@@ -31447,7 +32527,7 @@ async function collectSourceFiles(directory, onProgress) {
|
|
|
31447
32527
|
const entries = await readdir3(currentDirectory, { withFileTypes: true });
|
|
31448
32528
|
const subdirs = [];
|
|
31449
32529
|
for (const entry of entries) {
|
|
31450
|
-
const fullPath =
|
|
32530
|
+
const fullPath = join28(currentDirectory, entry.name);
|
|
31451
32531
|
if (entry.isDirectory()) {
|
|
31452
32532
|
if (!IGNORED_DIRECTORY_NAMES.has(entry.name)) {
|
|
31453
32533
|
subdirs.push(fullPath);
|
|
@@ -31474,6 +32554,12 @@ async function collectSourceFiles(directory, onProgress) {
|
|
|
31474
32554
|
await visit(directory);
|
|
31475
32555
|
return files.sort();
|
|
31476
32556
|
}
|
|
32557
|
+
function resolveCompositionAgentName(flagValue) {
|
|
32558
|
+
if (flagValue && isAgentName(flagValue)) return flagValue;
|
|
32559
|
+
const env = process.env["EDS_COMPOSITION_AGENT"];
|
|
32560
|
+
if (env && isAgentName(env)) return env;
|
|
32561
|
+
return DEFAULT_AGENT_NAME;
|
|
32562
|
+
}
|
|
31477
32563
|
async function readCandidateFiles(components, extraFiles = []) {
|
|
31478
32564
|
const paths = new Set(extraFiles);
|
|
31479
32565
|
for (const c2 of components) {
|
|
@@ -31483,7 +32569,7 @@ async function readCandidateFiles(components, extraFiles = []) {
|
|
|
31483
32569
|
await Promise.all(
|
|
31484
32570
|
[...paths].map(async (p) => {
|
|
31485
32571
|
try {
|
|
31486
|
-
const content = await
|
|
32572
|
+
const content = await readFile19(p, "utf8");
|
|
31487
32573
|
out.push({ path: p, content });
|
|
31488
32574
|
} catch {
|
|
31489
32575
|
}
|
|
@@ -31492,11 +32578,21 @@ async function readCandidateFiles(components, extraFiles = []) {
|
|
|
31492
32578
|
return out;
|
|
31493
32579
|
}
|
|
31494
32580
|
function registerInternalExtractCommand(program) {
|
|
31495
|
-
program.command("__extract", { hidden: true }).description("Extract component definitions from a project").requiredOption("--project <path>", "Path to the project root").option("--dir <path>", "Path to the component source directory relative to the project root").option(
|
|
32581
|
+
const extractCmd = program.command("__extract", { hidden: true }).description("Extract component definitions from a project").requiredOption("--project <path>", "Path to the project root").option("--dir <path>", "Path to the component source directory relative to the project root").option(
|
|
31496
32582
|
"--resolve-unreachable <mode>",
|
|
31497
32583
|
"Retry pass for unresolved Svelte Props types: 'auto' (default), 'always', or 'never'",
|
|
31498
32584
|
"auto"
|
|
31499
|
-
).
|
|
32585
|
+
).option("--composition-refresh", "Force the mapping agent to run even where deterministic sources answered").option("--no-cache", "Re-run extraction even when all source files are unchanged").option(
|
|
32586
|
+
"--prompt <stage=value>",
|
|
32587
|
+
"Override a stage prompt (repeatable). value is a file path or literal text, e.g. --prompt composition=./p.md",
|
|
32588
|
+
(v, acc) => [...acc, v],
|
|
32589
|
+
[]
|
|
32590
|
+
);
|
|
32591
|
+
addAgentModelOptions(extractCmd, {
|
|
32592
|
+
includeModel: false,
|
|
32593
|
+
agentDescription: "Coding agent for composition mapping resolution (claude|codex|opencode|cursor)"
|
|
32594
|
+
}).action(async (opts) => {
|
|
32595
|
+
const noCache = resolveExtractNoCache(opts);
|
|
31500
32596
|
const resolveUnreachable = (() => {
|
|
31501
32597
|
const v = opts.resolveUnreachable ?? "auto";
|
|
31502
32598
|
if (v !== "auto" && v !== "always" && v !== "never") {
|
|
@@ -31506,8 +32602,16 @@ function registerInternalExtractCommand(program) {
|
|
|
31506
32602
|
}
|
|
31507
32603
|
return v;
|
|
31508
32604
|
})();
|
|
31509
|
-
|
|
31510
|
-
|
|
32605
|
+
if (opts.bedrock) {
|
|
32606
|
+
const bedrockAgent = resolveCompositionAgentName(opts.agent);
|
|
32607
|
+
if (!agentSupportsBedrock(bedrockAgent)) {
|
|
32608
|
+
process.stderr.write(`Error: --bedrock is not supported for --agent ${bedrockAgent}
|
|
32609
|
+
`);
|
|
32610
|
+
process.exit(1);
|
|
32611
|
+
}
|
|
32612
|
+
}
|
|
32613
|
+
const projectRoot = resolve20(opts.project);
|
|
32614
|
+
const outDir = join28(projectRoot, ".contentful");
|
|
31511
32615
|
let sourceDirectory;
|
|
31512
32616
|
if (opts.dir !== void 0) {
|
|
31513
32617
|
sourceDirectory = resolveFromProjectRoot(projectRoot, opts.dir);
|
|
@@ -31530,16 +32634,50 @@ function registerInternalExtractCommand(program) {
|
|
|
31530
32634
|
process.stderr.write(`progress=scan-done:${sourceFiles.length}
|
|
31531
32635
|
`);
|
|
31532
32636
|
}
|
|
31533
|
-
const
|
|
31534
|
-
|
|
31535
|
-
|
|
32637
|
+
const extractionCacheDb = openPipelineDb();
|
|
32638
|
+
let extraction;
|
|
32639
|
+
let extractionCacheHits = 0;
|
|
32640
|
+
try {
|
|
32641
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32642
|
+
const cachedByPath = /* @__PURE__ */ new Map();
|
|
32643
|
+
if (!noCache && sourceFiles.length > 0) {
|
|
32644
|
+
const hashes = await Promise.all(
|
|
32645
|
+
sourceFiles.map(async (filePath) => [filePath, await hashFile(filePath)])
|
|
32646
|
+
);
|
|
32647
|
+
for (const [filePath, fileHash] of hashes) {
|
|
32648
|
+
cachedByPath.set(filePath, lookupExtractCache(extractionCacheDb, fileHash, cacheVersion));
|
|
32649
|
+
}
|
|
32650
|
+
}
|
|
32651
|
+
const allFilesCached = !noCache && sourceFiles.length > 0 && sourceFiles.every((filePath) => cachedByPath.get(filePath) !== null);
|
|
32652
|
+
if (allFilesCached) {
|
|
32653
|
+
const cachedComponents = sourceFiles.flatMap((filePath) => cachedByPath.get(filePath).components);
|
|
32654
|
+
extractionCacheHits = sourceFiles.length;
|
|
32655
|
+
extraction = { components: cachedComponents, warnings: [], exclusions: [] };
|
|
31536
32656
|
if (!process.stdout.isTTY) {
|
|
31537
|
-
process.stderr.write(
|
|
31538
|
-
`
|
|
32657
|
+
process.stderr.write(
|
|
32658
|
+
`progress=extract:${sourceFiles.length}/${sourceFiles.length}:${cachedComponents.length}
|
|
32659
|
+
`
|
|
32660
|
+
);
|
|
31539
32661
|
}
|
|
31540
|
-
|
|
31541
|
-
|
|
31542
|
-
|
|
32662
|
+
getDebugLogger().event("analyze", "extract.cache-hit", {
|
|
32663
|
+
files: sourceFiles.length,
|
|
32664
|
+
components: cachedComponents.length
|
|
32665
|
+
});
|
|
32666
|
+
} else {
|
|
32667
|
+
extraction = await extractComponents(
|
|
32668
|
+
sourceFiles,
|
|
32669
|
+
({ filesProcessed, componentsFound }) => {
|
|
32670
|
+
if (!process.stdout.isTTY) {
|
|
32671
|
+
process.stderr.write(`progress=extract:${filesProcessed}/${sourceFiles.length}:${componentsFound}
|
|
32672
|
+
`);
|
|
32673
|
+
}
|
|
32674
|
+
},
|
|
32675
|
+
{ resolveUnreachable, projectRoot }
|
|
32676
|
+
);
|
|
32677
|
+
}
|
|
32678
|
+
} finally {
|
|
32679
|
+
extractionCacheDb.close();
|
|
32680
|
+
}
|
|
31543
32681
|
await mkdir6(outDir, { recursive: true });
|
|
31544
32682
|
const db = openPipelineDb();
|
|
31545
32683
|
const { sessionId: sessionId2 } = getOrCreateSession(db, void 0, void 0, {
|
|
@@ -31554,6 +32692,25 @@ function registerInternalExtractCommand(program) {
|
|
|
31554
32692
|
const stepId = createStep(db, sessionId2, "analyze extract", {
|
|
31555
32693
|
project: projectRoot
|
|
31556
32694
|
});
|
|
32695
|
+
if (extractionCacheHits === 0 && !noCache) {
|
|
32696
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32697
|
+
const componentsBySourcePath = /* @__PURE__ */ new Map();
|
|
32698
|
+
for (const component of extraction.components) {
|
|
32699
|
+
if (!component.sourcePath) continue;
|
|
32700
|
+
const components = componentsBySourcePath.get(component.sourcePath) ?? [];
|
|
32701
|
+
components.push(component);
|
|
32702
|
+
componentsBySourcePath.set(component.sourcePath, components);
|
|
32703
|
+
}
|
|
32704
|
+
for (const filePath of sourceFiles) {
|
|
32705
|
+
storeExtractCache(
|
|
32706
|
+
db,
|
|
32707
|
+
filePath,
|
|
32708
|
+
await hashFile(filePath),
|
|
32709
|
+
cacheVersion,
|
|
32710
|
+
componentsBySourcePath.get(filePath) ?? []
|
|
32711
|
+
);
|
|
32712
|
+
}
|
|
32713
|
+
}
|
|
31557
32714
|
const classifiedComponents = extraction.components.map(preClassifyComponent);
|
|
31558
32715
|
for (const exclusion of extraction.exclusions ?? []) {
|
|
31559
32716
|
getDebugLogger().event("filter", "extract.excluded", { ...exclusion });
|
|
@@ -31577,9 +32734,28 @@ function registerInternalExtractCommand(program) {
|
|
|
31577
32734
|
storeRawComponents(db, sessionId2, validatedComponents);
|
|
31578
32735
|
process.stdout.write(`session=${sessionId2}
|
|
31579
32736
|
`);
|
|
31580
|
-
let sourceCallSiteEvidence = [];
|
|
31581
|
-
let sourceCallSiteRejections = [];
|
|
31582
32737
|
{
|
|
32738
|
+
const sources = resolveCompositionSources({
|
|
32739
|
+
...opts,
|
|
32740
|
+
noCache
|
|
32741
|
+
});
|
|
32742
|
+
const { overrides: promptOverrides, errors: promptErrors } = parsePromptOverrides(opts.prompt ?? []);
|
|
32743
|
+
for (const err of promptErrors) {
|
|
32744
|
+
process.stderr.write(`Error: ${err}
|
|
32745
|
+
`);
|
|
32746
|
+
process.exit(1);
|
|
32747
|
+
}
|
|
32748
|
+
let compositionPrompt;
|
|
32749
|
+
const compositionOverride = promptOverrides.get("composition");
|
|
32750
|
+
if (compositionOverride) {
|
|
32751
|
+
try {
|
|
32752
|
+
compositionPrompt = await resolvePromptOverride(compositionOverride);
|
|
32753
|
+
} catch (e) {
|
|
32754
|
+
process.stderr.write(`Error: ${e instanceof Error ? e.message : String(e)}
|
|
32755
|
+
`);
|
|
32756
|
+
process.exit(1);
|
|
32757
|
+
}
|
|
32758
|
+
}
|
|
31583
32759
|
{
|
|
31584
32760
|
const emitCompositionProgress = (phase) => {
|
|
31585
32761
|
if (!process.stdout.isTTY) process.stderr.write(`progress=composition:${phase}
|
|
@@ -31587,18 +32763,62 @@ function registerInternalExtractCommand(program) {
|
|
|
31587
32763
|
};
|
|
31588
32764
|
emitCompositionProgress("resolving");
|
|
31589
32765
|
const allFiles = await readCandidateFiles(validatedComponents, sourceFiles);
|
|
32766
|
+
const selectedCandidates = selectCandidateFiles(allFiles).map((c2) => ({ path: c2.path, content: c2.content }));
|
|
32767
|
+
const capped = capCandidatesToPromptBudget(selectedCandidates);
|
|
32768
|
+
const promptFiles = capped.kept;
|
|
32769
|
+
if (capped.dropped.length > 0) {
|
|
32770
|
+
process.stderr.write(
|
|
32771
|
+
`Warning: composition \u2014 ${capped.dropped.length} candidate file(s) omitted from the agent prompt to fit the context budget; resolution runs on the ${promptFiles.length} highest-value files.
|
|
32772
|
+
`
|
|
32773
|
+
);
|
|
32774
|
+
}
|
|
31590
32775
|
const runtimeFiles = allFiles.map((c2) => ({ path: c2.path, content: c2.content }));
|
|
32776
|
+
const resolverAgent = resolveCompositionAgentName(opts.agent);
|
|
31591
32777
|
const componentNameSet = new Set(validatedComponents.map((c2) => c2.name));
|
|
32778
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32779
|
+
let lastAgentExitCode = 0;
|
|
32780
|
+
const spawnAgent = async (prompt) => {
|
|
32781
|
+
const res = await runAgent({
|
|
32782
|
+
agent: resolverAgent,
|
|
32783
|
+
prompt,
|
|
32784
|
+
timeoutMs: 12e4,
|
|
32785
|
+
promptViaStdin: true,
|
|
32786
|
+
onDebugEvent: (name, payload) => getDebugLogger().event("agent", name, payload)
|
|
32787
|
+
});
|
|
32788
|
+
lastAgentExitCode = res.exitCode;
|
|
32789
|
+
if (res.exitCode !== 0 && res.stderr.trim()) {
|
|
32790
|
+
process.stderr.write(`Warning: composition \u2014 agent exited ${res.exitCode}: ${res.stderr.trim()}
|
|
32791
|
+
`);
|
|
32792
|
+
}
|
|
32793
|
+
return res.stdout;
|
|
32794
|
+
};
|
|
31592
32795
|
const manifestDocEdges = collectManifestDocEdges(runtimeFiles, validatedComponents, componentNameSet);
|
|
31593
32796
|
const extraEdges = manifestDocEdges;
|
|
31594
|
-
const
|
|
31595
|
-
|
|
31596
|
-
|
|
31597
|
-
|
|
32797
|
+
const agentCacheKey = buildCompositionInputHash({
|
|
32798
|
+
files: promptFiles,
|
|
32799
|
+
agent: resolverAgent
|
|
32800
|
+
});
|
|
32801
|
+
const result = await resolveMapping({
|
|
31598
32802
|
components: validatedComponents,
|
|
31599
32803
|
...extraEdges.length > 0 ? { extraEdges } : {},
|
|
31600
|
-
|
|
31601
|
-
|
|
32804
|
+
forceAgent: sources.forceAgent,
|
|
32805
|
+
files: promptFiles,
|
|
32806
|
+
...compositionPrompt ? { promptOverride: compositionPrompt } : {},
|
|
32807
|
+
runAgentFn: async ({ prompt }) => {
|
|
32808
|
+
if (!noCache && !opts.compositionRefresh) {
|
|
32809
|
+
const cached = lookupCompositionCache(db, agentCacheKey, cacheVersion);
|
|
32810
|
+
if (cached !== null) {
|
|
32811
|
+
emitCompositionProgress("cache-hit");
|
|
32812
|
+
return cached;
|
|
32813
|
+
}
|
|
32814
|
+
}
|
|
32815
|
+
emitCompositionProgress(`agent:${resolverAgent}`);
|
|
32816
|
+
const stdout = await spawnAgent(prompt);
|
|
32817
|
+
if (lastAgentExitCode === 0) {
|
|
32818
|
+
storeCompositionCache(db, agentCacheKey, cacheVersion, stdout);
|
|
32819
|
+
}
|
|
32820
|
+
return stdout;
|
|
32821
|
+
}
|
|
31602
32822
|
});
|
|
31603
32823
|
emitCompositionProgress("done");
|
|
31604
32824
|
for (const w of result.warnings) process.stderr.write(`Warning: composition \u2014 ${w}
|
|
@@ -31628,13 +32848,7 @@ function registerInternalExtractCommand(program) {
|
|
|
31628
32848
|
sessionId2,
|
|
31629
32849
|
sourceFiles.map((f) => relative2(projectRoot, f))
|
|
31630
32850
|
);
|
|
31631
|
-
await retryDatabaseWrite(
|
|
31632
|
-
() => updateStep(db, stepId, "complete", {
|
|
31633
|
-
sessionId: sessionId2,
|
|
31634
|
-
compositionEvidence: JSON.stringify(sourceCallSiteEvidence),
|
|
31635
|
-
compositionRejections: JSON.stringify(sourceCallSiteRejections)
|
|
31636
|
-
})
|
|
31637
|
-
);
|
|
32851
|
+
await retryDatabaseWrite(() => updateStep(db, stepId, "complete", { sessionId: sessionId2 }));
|
|
31638
32852
|
enrichCommandResult({ extracted_component_count: validatedComponents.length });
|
|
31639
32853
|
db.close();
|
|
31640
32854
|
const allWarnings = [...extraction.warnings, ...filterWarnings];
|
|
@@ -31656,12 +32870,18 @@ var SCANNED_FILE_EXTENSIONS, DENYLIST_GATED_EXTENSIONS, DENYLISTED_EXACT_FILE_NA
|
|
|
31656
32870
|
var init_extract_command = __esm({
|
|
31657
32871
|
"packages/experience-design-system-cli-legacy/src/analyze/extract-command.ts"() {
|
|
31658
32872
|
"use strict";
|
|
32873
|
+
init_agent_model_options();
|
|
31659
32874
|
init_src2();
|
|
31660
32875
|
init_db();
|
|
32876
|
+
init_cache_keys();
|
|
31661
32877
|
init_cycle_detection();
|
|
31662
32878
|
init_resolve_mapping();
|
|
32879
|
+
init_resolve_mapping_cli();
|
|
32880
|
+
init_candidate_files();
|
|
32881
|
+
init_composition_cache_key();
|
|
31663
32882
|
init_manifest_doc_evidence();
|
|
31664
|
-
|
|
32883
|
+
init_prompt_overrides();
|
|
32884
|
+
init_src();
|
|
31665
32885
|
init_analytics();
|
|
31666
32886
|
init_debug_logger();
|
|
31667
32887
|
SCANNED_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".astro", ".js", ".jsx", ".svelte", ".ts", ".tsx", ".vue"]);
|
|
@@ -31755,9 +32975,9 @@ __export(program_exports, {
|
|
|
31755
32975
|
runBuild: () => runBuild
|
|
31756
32976
|
});
|
|
31757
32977
|
import { spawn as spawn7 } from "node:child_process";
|
|
31758
|
-
import { fileURLToPath as
|
|
31759
|
-
import { dirname as
|
|
31760
|
-
import { readFileSync as
|
|
32978
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
32979
|
+
import { dirname as dirname19, join as join29, resolve as resolve21 } from "node:path";
|
|
32980
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
31761
32981
|
import { Command } from "commander";
|
|
31762
32982
|
async function runBuild(opts) {
|
|
31763
32983
|
return new Promise((resolvePromise) => {
|
|
@@ -31786,7 +33006,7 @@ function resolveBedrockFromAncestors(actionCommand) {
|
|
|
31786
33006
|
}
|
|
31787
33007
|
function registerBuildCommand(program) {
|
|
31788
33008
|
program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").helpOption(false).action(async () => {
|
|
31789
|
-
const pkgRoot =
|
|
33009
|
+
const pkgRoot = resolve21(dirname19(fileURLToPath4(import.meta.url)), "..", "..");
|
|
31790
33010
|
process.stderr.write("\u2699 Building from source...\n");
|
|
31791
33011
|
const { exitCode } = await runBuild({
|
|
31792
33012
|
spawnFn: () => spawn7("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|
|
@@ -31856,7 +33076,7 @@ var init_program = __esm({
|
|
|
31856
33076
|
init_analytics();
|
|
31857
33077
|
init_credentials_store();
|
|
31858
33078
|
init_cli_path();
|
|
31859
|
-
pkg3 = JSON.parse(
|
|
33079
|
+
pkg3 = JSON.parse(readFileSync11(join29(findPkgRoot(), "package.json"), "utf8"));
|
|
31860
33080
|
}
|
|
31861
33081
|
});
|
|
31862
33082
|
|