@contentful/experience-design-system-cli 2.35.1-dev-build-5446cce7.0 → 2.35.1-dev-build-4f1ad8cb.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- 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 +1324 -180
- 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 -1
- package/package.json +2 -2
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";
|
|
@@ -612,6 +630,17 @@ var init_build_prompt = __esm({
|
|
|
612
630
|
});
|
|
613
631
|
|
|
614
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
|
+
}
|
|
615
644
|
var init_execute_generation_orchestrator = __esm({
|
|
616
645
|
"packages/experience-design-system-generation/dist/src/orchestrator/execute-generation-orchestrator.js"() {
|
|
617
646
|
"use strict";
|
|
@@ -712,6 +741,22 @@ var init_describe_agent_failure = __esm({
|
|
|
712
741
|
});
|
|
713
742
|
|
|
714
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
|
+
}
|
|
715
760
|
var init_extract_sentinel_output = __esm({
|
|
716
761
|
"packages/experience-design-system-generation/dist/src/services/agent/helpers/extract-sentinel-output.js"() {
|
|
717
762
|
"use strict";
|
|
@@ -736,7 +781,7 @@ async function runAgent(options) {
|
|
|
736
781
|
promptLen: prompt.length,
|
|
737
782
|
promptHead: prompt.slice(0, 500)
|
|
738
783
|
});
|
|
739
|
-
return new Promise((
|
|
784
|
+
return new Promise((resolve21) => {
|
|
740
785
|
const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
|
|
741
786
|
const child = spawn(binary, args, {
|
|
742
787
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -785,7 +830,7 @@ async function runAgent(options) {
|
|
|
785
830
|
stderrLen: stderr.length,
|
|
786
831
|
stderrTail: stderr.slice(-1e3)
|
|
787
832
|
});
|
|
788
|
-
|
|
833
|
+
resolve21(result);
|
|
789
834
|
});
|
|
790
835
|
});
|
|
791
836
|
}
|
|
@@ -802,7 +847,7 @@ var init_run_agent = __esm({
|
|
|
802
847
|
// packages/experience-design-system-generation/dist/src/services/agent/helpers/check-claude-auth.js
|
|
803
848
|
import { spawn as spawn2 } from "node:child_process";
|
|
804
849
|
function checkClaudeAuth(binary) {
|
|
805
|
-
return new Promise((
|
|
850
|
+
return new Promise((resolve21) => {
|
|
806
851
|
const child = spawn2(binary, ["auth", "status", "--json"], {
|
|
807
852
|
stdio: ["ignore", "pipe", "pipe"]
|
|
808
853
|
});
|
|
@@ -812,7 +857,7 @@ function checkClaudeAuth(binary) {
|
|
|
812
857
|
if (!done) {
|
|
813
858
|
done = true;
|
|
814
859
|
child.kill("SIGTERM");
|
|
815
|
-
|
|
860
|
+
resolve21("unauthenticated");
|
|
816
861
|
}
|
|
817
862
|
}, 5e3);
|
|
818
863
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -824,14 +869,14 @@ function checkClaudeAuth(binary) {
|
|
|
824
869
|
done = true;
|
|
825
870
|
clearTimeout(timer);
|
|
826
871
|
if (code !== 0) {
|
|
827
|
-
|
|
872
|
+
resolve21("unauthenticated");
|
|
828
873
|
return;
|
|
829
874
|
}
|
|
830
875
|
try {
|
|
831
876
|
const status = JSON.parse(stdout);
|
|
832
|
-
|
|
877
|
+
resolve21(status.loggedIn ? "ok" : "unauthenticated");
|
|
833
878
|
} catch {
|
|
834
|
-
|
|
879
|
+
resolve21("unauthenticated");
|
|
835
880
|
}
|
|
836
881
|
});
|
|
837
882
|
});
|
|
@@ -846,13 +891,13 @@ var init_check_claude_auth = __esm({
|
|
|
846
891
|
import { spawn as spawn3 } from "node:child_process";
|
|
847
892
|
async function checkAgentAuth(agent) {
|
|
848
893
|
const binary = resolveAgentBinary(agent);
|
|
849
|
-
const binaryExists2 = await new Promise((
|
|
894
|
+
const binaryExists2 = await new Promise((resolve21) => {
|
|
850
895
|
if (binary.startsWith("/")) {
|
|
851
|
-
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() =>
|
|
896
|
+
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() => resolve21(true), () => resolve21(false)));
|
|
852
897
|
return;
|
|
853
898
|
}
|
|
854
899
|
const child = spawn3(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
|
|
855
|
-
child.on("close", (code) =>
|
|
900
|
+
child.on("close", (code) => resolve21(code === 0));
|
|
856
901
|
});
|
|
857
902
|
if (!binaryExists2)
|
|
858
903
|
return "not-found";
|
|
@@ -889,6 +934,20 @@ var init_local_cli_agent_invoker = __esm({
|
|
|
889
934
|
});
|
|
890
935
|
|
|
891
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
|
+
}
|
|
892
951
|
var init_create_generation_endpoint = __esm({
|
|
893
952
|
"packages/experience-design-system-generation/dist/src/controller/create-generation-endpoint.js"() {
|
|
894
953
|
"use strict";
|
|
@@ -1273,6 +1332,32 @@ var init_progress = __esm({
|
|
|
1273
1332
|
});
|
|
1274
1333
|
|
|
1275
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
|
+
});
|
|
1276
1361
|
var init_src = __esm({
|
|
1277
1362
|
"packages/experience-design-system-generation/dist/src/index.js"() {
|
|
1278
1363
|
"use strict";
|
|
@@ -10308,6 +10393,41 @@ var init_read3 = __esm({
|
|
|
10308
10393
|
}
|
|
10309
10394
|
});
|
|
10310
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
|
+
|
|
10311
10431
|
// packages/experience-design-system-cli-legacy/src/session/repositories/tokens/write.ts
|
|
10312
10432
|
function deleteRawTokensForSession(db, sessionId2) {
|
|
10313
10433
|
db.prepare("DELETE FROM raw_token_groups WHERE session_id = ?").run(sessionId2);
|
|
@@ -10471,17 +10591,47 @@ var init_replace_raw_prop_token_paths = __esm({
|
|
|
10471
10591
|
}
|
|
10472
10592
|
});
|
|
10473
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
|
+
|
|
10474
10623
|
// packages/experience-design-system-cli-legacy/src/session/db.ts
|
|
10475
10624
|
import { DatabaseSync } from "node:sqlite";
|
|
10476
10625
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
10477
|
-
import { readFile as
|
|
10626
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
10627
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
10478
10628
|
import { homedir as homedir3 } from "node:os";
|
|
10479
|
-
import { dirname as dirname14, resolve as
|
|
10629
|
+
import { dirname as dirname14, resolve as resolve9 } from "node:path";
|
|
10480
10630
|
function getPipelineDbPath() {
|
|
10481
10631
|
if (process.env.EDS_PIPELINE_DB_PATH) {
|
|
10482
|
-
return
|
|
10632
|
+
return resolve9(process.env.EDS_PIPELINE_DB_PATH);
|
|
10483
10633
|
}
|
|
10484
|
-
return
|
|
10634
|
+
return resolve9(homedir3(), ".contentful", "experience-design-system-cli", "pipeline.db");
|
|
10485
10635
|
}
|
|
10486
10636
|
function openPipelineDb(dbPath) {
|
|
10487
10637
|
const path = dbPath ?? getPipelineDbPath();
|
|
@@ -10615,8 +10765,134 @@ function applyDbMigrations(db) {
|
|
|
10615
10765
|
if (!rawSlotColsForRationale.some((c2) => c2.name === "rationale")) {
|
|
10616
10766
|
db.exec("ALTER TABLE raw_slots ADD COLUMN rationale TEXT");
|
|
10617
10767
|
}
|
|
10618
|
-
|
|
10619
|
-
|
|
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
|
+
`);
|
|
10620
10896
|
}
|
|
10621
10897
|
}
|
|
10622
10898
|
function loadComponentReviewMetadata(db, sessionId2, componentName) {
|
|
@@ -11152,16 +11428,16 @@ function extractRelativeImportPaths(sourceText) {
|
|
|
11152
11428
|
return [...specifiers];
|
|
11153
11429
|
}
|
|
11154
11430
|
async function resolveRelativeImport(specifier, fromDir) {
|
|
11155
|
-
const basePath =
|
|
11431
|
+
const basePath = resolve9(fromDir, specifier);
|
|
11156
11432
|
const candidates = [
|
|
11157
11433
|
basePath,
|
|
11158
11434
|
...rewrittenSourcePaths(basePath),
|
|
11159
11435
|
...SIBLING_FILE_EXTENSIONS.map((ext) => `${basePath}${ext}`),
|
|
11160
|
-
...SIBLING_FILE_EXTENSIONS.map((ext) =>
|
|
11436
|
+
...SIBLING_FILE_EXTENSIONS.map((ext) => resolve9(basePath, `index${ext}`))
|
|
11161
11437
|
];
|
|
11162
11438
|
for (const candidate of candidates) {
|
|
11163
11439
|
try {
|
|
11164
|
-
await
|
|
11440
|
+
await readFile8(candidate, "utf8");
|
|
11165
11441
|
return candidate;
|
|
11166
11442
|
} catch {
|
|
11167
11443
|
}
|
|
@@ -11177,7 +11453,7 @@ async function resolveImportSpecifiers(sourceText, fromDir) {
|
|
|
11177
11453
|
return resolvedPaths;
|
|
11178
11454
|
}
|
|
11179
11455
|
async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateTypeNames = []) {
|
|
11180
|
-
const visited = /* @__PURE__ */ new Set([
|
|
11456
|
+
const visited = /* @__PURE__ */ new Set([resolve9(sourcePath)]);
|
|
11181
11457
|
const discovered = [];
|
|
11182
11458
|
let frontier = [{ text: sourceText, dir: dirname14(sourcePath) }];
|
|
11183
11459
|
for (let hop = 0; hop < MAX_SIBLING_DEPTH && discovered.length < MAX_SIBLING_CANDIDATES_EXPLORED; hop++) {
|
|
@@ -11191,7 +11467,7 @@ async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateType
|
|
|
11191
11467
|
if (discovered.length >= MAX_SIBLING_CANDIDATES_EXPLORED) break;
|
|
11192
11468
|
let content;
|
|
11193
11469
|
try {
|
|
11194
|
-
content = await
|
|
11470
|
+
content = await readFile8(resolvedPath, "utf8");
|
|
11195
11471
|
} catch {
|
|
11196
11472
|
continue;
|
|
11197
11473
|
}
|
|
@@ -11228,7 +11504,7 @@ async function loadComponentSourceRef(name, sourcePath, propNames = [], propType
|
|
|
11228
11504
|
let truncatedSiblingCount = 0;
|
|
11229
11505
|
const usesNotShown = /* @__PURE__ */ new Set();
|
|
11230
11506
|
try {
|
|
11231
|
-
const rawText = await
|
|
11507
|
+
const rawText = await readFile8(sourcePath, "utf8");
|
|
11232
11508
|
let siblingUsesNotShown;
|
|
11233
11509
|
let declaredTypeNames;
|
|
11234
11510
|
({
|
|
@@ -11664,6 +11940,108 @@ function backfillUnclassifiedProps(db, sessionId2) {
|
|
|
11664
11940
|
).run(sessionId2, sessionId2);
|
|
11665
11941
|
return Number(withCategory.changes) + Number(withoutCategory.changes);
|
|
11666
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
|
+
}
|
|
11667
12045
|
function storeScannedFiles(db, sessionId2, filePaths) {
|
|
11668
12046
|
db.exec("BEGIN");
|
|
11669
12047
|
try {
|
|
@@ -11746,7 +12124,105 @@ function filterUnknownSlotAllowedComponents(db, sessionId2, allowedComponentName
|
|
|
11746
12124
|
}
|
|
11747
12125
|
return unknown;
|
|
11748
12126
|
}
|
|
11749
|
-
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) {
|
|
11750
12226
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11751
12227
|
db.exec("BEGIN");
|
|
11752
12228
|
try {
|
|
@@ -11767,7 +12243,139 @@ function copyTokensBetweenSessions(db, sourceSessionId, targetSessionId) {
|
|
|
11767
12243
|
throw e;
|
|
11768
12244
|
}
|
|
11769
12245
|
}
|
|
11770
|
-
|
|
12246
|
+
function copyMapTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
12247
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12248
|
+
let copiedCount = 0;
|
|
12249
|
+
db.exec("BEGIN");
|
|
12250
|
+
try {
|
|
12251
|
+
const sourceRows = db.prepare(
|
|
12252
|
+
`SELECT rc.name AS component_name, rptp.prop_name, rptp.source, rptp.position, rptp.path
|
|
12253
|
+
FROM raw_prop_token_paths rptp
|
|
12254
|
+
JOIN raw_components rc ON rc.session_id = rptp.session_id AND rc.component_id = rptp.component_id
|
|
12255
|
+
WHERE rptp.session_id = ?
|
|
12256
|
+
ORDER BY rc.name, rptp.prop_name, rptp.position`
|
|
12257
|
+
).all(sourceSessionId);
|
|
12258
|
+
const targetComponents = db.prepare(`SELECT component_id, name FROM raw_components WHERE session_id = ?`).all(targetSessionId);
|
|
12259
|
+
const targetIdByName = new Map(targetComponents.map((c2) => [c2.name, c2.component_id]));
|
|
12260
|
+
const targetProps = new Set(
|
|
12261
|
+
db.prepare(`SELECT component_id, name FROM raw_props WHERE session_id = ?`).all(targetSessionId).map((p) => `${p.component_id}::${p.name}`)
|
|
12262
|
+
);
|
|
12263
|
+
const insertPath = db.prepare(
|
|
12264
|
+
`INSERT INTO raw_prop_token_paths (session_id, component_id, prop_name, source, position, path)
|
|
12265
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
12266
|
+
);
|
|
12267
|
+
const clearedProps = /* @__PURE__ */ new Set();
|
|
12268
|
+
const copiedProps = /* @__PURE__ */ new Set();
|
|
12269
|
+
for (const row of sourceRows) {
|
|
12270
|
+
const targetComponentId = targetIdByName.get(row.component_name);
|
|
12271
|
+
if (!targetComponentId) continue;
|
|
12272
|
+
if (!targetProps.has(`${targetComponentId}::${row.prop_name}`)) continue;
|
|
12273
|
+
const propKey = `${targetComponentId}::${row.prop_name}`;
|
|
12274
|
+
if (!clearedProps.has(propKey)) {
|
|
12275
|
+
clearedProps.add(propKey);
|
|
12276
|
+
db.prepare(`DELETE FROM raw_prop_token_paths WHERE session_id = ? AND component_id = ? AND prop_name = ?`).run(
|
|
12277
|
+
targetSessionId,
|
|
12278
|
+
targetComponentId,
|
|
12279
|
+
row.prop_name
|
|
12280
|
+
);
|
|
12281
|
+
}
|
|
12282
|
+
insertPath.run(targetSessionId, targetComponentId, row.prop_name, row.source, row.position, row.path);
|
|
12283
|
+
copiedProps.add(propKey);
|
|
12284
|
+
}
|
|
12285
|
+
copiedCount = copiedProps.size;
|
|
12286
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12287
|
+
db.exec("COMMIT");
|
|
12288
|
+
} catch (e) {
|
|
12289
|
+
db.exec("ROLLBACK");
|
|
12290
|
+
throw e;
|
|
12291
|
+
}
|
|
12292
|
+
return copiedCount;
|
|
12293
|
+
}
|
|
12294
|
+
async function getCliCacheVersion() {
|
|
12295
|
+
if (_cliCacheVersionCache) return _cliCacheVersionCache;
|
|
12296
|
+
try {
|
|
12297
|
+
const { hashContent: hashContent2 } = await Promise.resolve().then(() => (init_cache_keys(), cache_keys_exports));
|
|
12298
|
+
const { resolveSkillPath: resolveSkillPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
12299
|
+
const skills = ["components", "tokens", "select"];
|
|
12300
|
+
const parts = [];
|
|
12301
|
+
for (const s of skills) {
|
|
12302
|
+
try {
|
|
12303
|
+
const p = resolveSkillPath2(s);
|
|
12304
|
+
parts.push(readFileSync5(p, "utf8"));
|
|
12305
|
+
} catch {
|
|
12306
|
+
parts.push(`<missing:${s}>`);
|
|
12307
|
+
}
|
|
12308
|
+
}
|
|
12309
|
+
_cliCacheVersionCache = hashContent2(parts.join("\n---\n"));
|
|
12310
|
+
return _cliCacheVersionCache;
|
|
12311
|
+
} catch {
|
|
12312
|
+
_cliCacheVersionCache = "fallback";
|
|
12313
|
+
return _cliCacheVersionCache;
|
|
12314
|
+
}
|
|
12315
|
+
}
|
|
12316
|
+
function storeExtractCache(db, filePath, fileHash, cliVersion2, components) {
|
|
12317
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12318
|
+
const componentsJson = JSON.stringify(components);
|
|
12319
|
+
db.prepare(
|
|
12320
|
+
`INSERT INTO extract_cache (file_path, file_hash, cli_version, created_at, updated_at, components_json)
|
|
12321
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
12322
|
+
ON CONFLICT(file_hash, cli_version) DO UPDATE SET
|
|
12323
|
+
file_path = excluded.file_path,
|
|
12324
|
+
updated_at = excluded.updated_at,
|
|
12325
|
+
components_json = excluded.components_json`
|
|
12326
|
+
).run(filePath, fileHash, cliVersion2, now, now, componentsJson);
|
|
12327
|
+
}
|
|
12328
|
+
function lookupExtractCache(db, fileHash, cliVersion2) {
|
|
12329
|
+
const row = db.prepare(
|
|
12330
|
+
`SELECT file_path, file_hash, cli_version, created_at, updated_at, components_json
|
|
12331
|
+
FROM extract_cache
|
|
12332
|
+
WHERE file_hash = ? AND cli_version = ?`
|
|
12333
|
+
).get(fileHash, cliVersion2);
|
|
12334
|
+
if (!row) return null;
|
|
12335
|
+
let components = [];
|
|
12336
|
+
try {
|
|
12337
|
+
components = JSON.parse(row.components_json);
|
|
12338
|
+
} catch {
|
|
12339
|
+
return null;
|
|
12340
|
+
}
|
|
12341
|
+
return {
|
|
12342
|
+
filePath: row.file_path,
|
|
12343
|
+
fileHash: row.file_hash,
|
|
12344
|
+
cliVersion: row.cli_version,
|
|
12345
|
+
createdAt: row.created_at,
|
|
12346
|
+
updatedAt: row.updated_at,
|
|
12347
|
+
components
|
|
12348
|
+
};
|
|
12349
|
+
}
|
|
12350
|
+
function storeSelectCache(db, componentHash, promptHash, cliVersion2, decision, reason) {
|
|
12351
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12352
|
+
db.prepare(
|
|
12353
|
+
`INSERT INTO select_cache (component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at)
|
|
12354
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
12355
|
+
ON CONFLICT(component_hash, prompt_hash, cli_version) DO UPDATE SET
|
|
12356
|
+
decision = excluded.decision,
|
|
12357
|
+
reason = excluded.reason,
|
|
12358
|
+
updated_at = excluded.updated_at`
|
|
12359
|
+
).run(componentHash, promptHash, cliVersion2, decision, reason, now, now);
|
|
12360
|
+
}
|
|
12361
|
+
function lookupSelectCache(db, componentHash, promptHash, cliVersion2) {
|
|
12362
|
+
const row = db.prepare(
|
|
12363
|
+
`SELECT component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at
|
|
12364
|
+
FROM select_cache
|
|
12365
|
+
WHERE component_hash = ? AND prompt_hash = ? AND cli_version = ?`
|
|
12366
|
+
).get(componentHash, promptHash, cliVersion2);
|
|
12367
|
+
if (!row) return null;
|
|
12368
|
+
return {
|
|
12369
|
+
componentHash: row.component_hash,
|
|
12370
|
+
promptHash: row.prompt_hash,
|
|
12371
|
+
cliVersion: row.cli_version,
|
|
12372
|
+
decision: row.decision,
|
|
12373
|
+
reason: row.reason,
|
|
12374
|
+
createdAt: row.created_at,
|
|
12375
|
+
updatedAt: row.updated_at
|
|
12376
|
+
};
|
|
12377
|
+
}
|
|
12378
|
+
var SCHEMA, MAX_COMPONENT_SOURCE_CHARS, MAX_SIBLING_FILES, MAX_SIBLING_SNIPPET_CHARS, MAX_TYPE_DECLARING_SIBLING_CHARS, MAX_ENLARGED_SIBLINGS, MAX_SIBLING_DEPTH, MAX_SIBLING_CANDIDATES_EXPLORED, RELATIVE_IMPORT_PATTERN, SIBLING_FILE_EXTENSIONS, TS_ESM_EXTENSION_REWRITES, IDENTIFIER_PATTERN, _cliCacheVersionCache;
|
|
11771
12379
|
var init_db = __esm({
|
|
11772
12380
|
"packages/experience-design-system-cli-legacy/src/session/db.ts"() {
|
|
11773
12381
|
"use strict";
|
|
@@ -11781,6 +12389,8 @@ var init_db = __esm({
|
|
|
11781
12389
|
init_write2();
|
|
11782
12390
|
init_session_resolver();
|
|
11783
12391
|
init_read3();
|
|
12392
|
+
init_hash_component_shape();
|
|
12393
|
+
init_hash_token_content();
|
|
11784
12394
|
init_read3();
|
|
11785
12395
|
init_store_dtcg_tokens();
|
|
11786
12396
|
init_apply_tool_calls();
|
|
@@ -11904,6 +12514,17 @@ CREATE TABLE IF NOT EXISTS raw_tokens (
|
|
|
11904
12514
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
11905
12515
|
);
|
|
11906
12516
|
|
|
12517
|
+
CREATE TABLE IF NOT EXISTS generation_cache (
|
|
12518
|
+
input_hash TEXT NOT NULL,
|
|
12519
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
12520
|
+
entity_id TEXT NOT NULL,
|
|
12521
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
12522
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
12523
|
+
created_at TEXT NOT NULL,
|
|
12524
|
+
updated_at TEXT NOT NULL,
|
|
12525
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
12526
|
+
);
|
|
12527
|
+
|
|
11907
12528
|
CREATE TABLE IF NOT EXISTS scanned_files (
|
|
11908
12529
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
11909
12530
|
path TEXT NOT NULL,
|
|
@@ -11949,9 +12570,10 @@ CREATE INDEX IF NOT EXISTS idx_raw_props_session ON raw_props(session_id,
|
|
|
11949
12570
|
CREATE INDEX IF NOT EXISTS idx_raw_slots_session ON raw_slots(session_id, component_id);
|
|
11950
12571
|
CREATE INDEX IF NOT EXISTS idx_raw_tokens_session ON raw_tokens(session_id);
|
|
11951
12572
|
CREATE INDEX IF NOT EXISTS idx_raw_token_groups_session ON raw_token_groups(session_id);
|
|
12573
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
12574
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
11952
12575
|
CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session_id);
|
|
11953
12576
|
`;
|
|
11954
|
-
REMOVED_CACHE_TABLES = ["generation_cache", "extract_cache", "composition_cache", "select_cache"];
|
|
11955
12577
|
MAX_COMPONENT_SOURCE_CHARS = 8e3;
|
|
11956
12578
|
MAX_SIBLING_FILES = 5;
|
|
11957
12579
|
MAX_SIBLING_SNIPPET_CHARS = 1200;
|
|
@@ -11968,15 +12590,16 @@ CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session
|
|
|
11968
12590
|
[".cjs", [".cts", ".cjs"]]
|
|
11969
12591
|
];
|
|
11970
12592
|
IDENTIFIER_PATTERN = /[A-Za-z_$][A-Za-z0-9_$]*/g;
|
|
12593
|
+
_cliCacheVersionCache = null;
|
|
11971
12594
|
}
|
|
11972
12595
|
});
|
|
11973
12596
|
|
|
11974
12597
|
// packages/experience-design-system-cli-legacy/src/helpers/read-existing-contentful-entities-from-session.ts
|
|
11975
|
-
import { readFile as
|
|
12598
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
11976
12599
|
async function readExistingContentfulEntitiesFromSession(path) {
|
|
11977
12600
|
if (!path) return void 0;
|
|
11978
12601
|
try {
|
|
11979
|
-
const raw = await
|
|
12602
|
+
const raw = await readFile9(path, "utf8");
|
|
11980
12603
|
const parsed = JSON.parse(raw);
|
|
11981
12604
|
if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens)) return void 0;
|
|
11982
12605
|
return parsed;
|
|
@@ -12100,21 +12723,21 @@ var init_resolve_session_id = __esm({
|
|
|
12100
12723
|
});
|
|
12101
12724
|
|
|
12102
12725
|
// packages/experience-design-system-cli-legacy/src/analyze/select/persistence.ts
|
|
12103
|
-
import { access, appendFile, mkdir as mkdir2, readFile as
|
|
12726
|
+
import { access, appendFile, mkdir as mkdir2, readFile as readFile10, writeFile as writeFile2 } from "node:fs/promises";
|
|
12104
12727
|
import { homedir as homedir4 } from "node:os";
|
|
12105
|
-
import { resolve as
|
|
12728
|
+
import { resolve as resolve10 } from "node:path";
|
|
12106
12729
|
function getRefineArtifactsRoot() {
|
|
12107
12730
|
if (process.env.EDS_REVIEW_ARTIFACTS_DIR) {
|
|
12108
|
-
return
|
|
12731
|
+
return resolve10(process.env.EDS_REVIEW_ARTIFACTS_DIR);
|
|
12109
12732
|
}
|
|
12110
|
-
return
|
|
12733
|
+
return resolve10(homedir4(), ".contentful", "experience-design-system-cli", "reviews");
|
|
12111
12734
|
}
|
|
12112
12735
|
async function getRefineSessionPaths(sessionId2, artifactsRoot) {
|
|
12113
|
-
const sessionDir =
|
|
12736
|
+
const sessionDir = resolve10(artifactsRoot, sessionId2);
|
|
12114
12737
|
return {
|
|
12115
12738
|
sessionDir,
|
|
12116
|
-
eventsPath:
|
|
12117
|
-
statePath:
|
|
12739
|
+
eventsPath: resolve10(sessionDir, "events.jsonl"),
|
|
12740
|
+
statePath: resolve10(sessionDir, "current-review-state.json")
|
|
12118
12741
|
};
|
|
12119
12742
|
}
|
|
12120
12743
|
async function saveReviewState(statePath, session) {
|
|
@@ -12125,7 +12748,7 @@ async function ensureRefineSession(sessionId2, artifactsRoot, initialSnapshot) {
|
|
|
12125
12748
|
await mkdir2(paths.sessionDir, { recursive: true });
|
|
12126
12749
|
try {
|
|
12127
12750
|
await access(paths.statePath);
|
|
12128
|
-
const savedState = await
|
|
12751
|
+
const savedState = await readFile10(paths.statePath, "utf8");
|
|
12129
12752
|
return JSON.parse(savedState);
|
|
12130
12753
|
} catch {
|
|
12131
12754
|
await writeFile2(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
|
|
@@ -12610,8 +13233,8 @@ var init_path_exists = __esm({
|
|
|
12610
13233
|
});
|
|
12611
13234
|
|
|
12612
13235
|
// packages/experience-design-system-cli-legacy/src/lib/prompt-overrides.ts
|
|
12613
|
-
import { readFile as
|
|
12614
|
-
import { resolve as
|
|
13236
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
13237
|
+
import { resolve as resolve11 } from "node:path";
|
|
12615
13238
|
function looksLikePath(value) {
|
|
12616
13239
|
if (value.includes("/") || value.includes("\\")) return true;
|
|
12617
13240
|
if (value.startsWith("~")) return true;
|
|
@@ -12643,9 +13266,9 @@ function parsePromptOverrides(inputs) {
|
|
|
12643
13266
|
}
|
|
12644
13267
|
async function resolvePromptOverride(override) {
|
|
12645
13268
|
if (override.kind === "text") return override.value;
|
|
12646
|
-
const abs =
|
|
13269
|
+
const abs = resolve11(override.value);
|
|
12647
13270
|
try {
|
|
12648
|
-
return await
|
|
13271
|
+
return await readFile11(abs, "utf8");
|
|
12649
13272
|
} catch {
|
|
12650
13273
|
throw new Error(`--prompt: could not read prompt file: ${abs}`);
|
|
12651
13274
|
}
|
|
@@ -12660,21 +13283,21 @@ var init_prompt_overrides = __esm({
|
|
|
12660
13283
|
|
|
12661
13284
|
// packages/experience-design-system-cli-legacy/src/generate/command.ts
|
|
12662
13285
|
import { createElement } from "react";
|
|
12663
|
-
import { readFile as
|
|
12664
|
-
import { join as join14, resolve as
|
|
13286
|
+
import { readFile as readFile12, readdir, stat } from "node:fs/promises";
|
|
13287
|
+
import { join as join14, resolve as resolve12 } from "node:path";
|
|
12665
13288
|
async function assertFileExists(flag, p) {
|
|
12666
13289
|
if (!await pathExists(p)) die(`Error: file not found: ${p} (from ${flag})`);
|
|
12667
13290
|
}
|
|
12668
13291
|
async function readFileInline(path) {
|
|
12669
13292
|
if (!path) return void 0;
|
|
12670
|
-
const resolved =
|
|
13293
|
+
const resolved = resolve12(path);
|
|
12671
13294
|
let s;
|
|
12672
13295
|
try {
|
|
12673
13296
|
s = await stat(resolved);
|
|
12674
13297
|
} catch {
|
|
12675
13298
|
return void 0;
|
|
12676
13299
|
}
|
|
12677
|
-
if (!s.isDirectory()) return
|
|
13300
|
+
if (!s.isDirectory()) return readFile12(resolved, "utf8");
|
|
12678
13301
|
const files = [];
|
|
12679
13302
|
async function walk(dir) {
|
|
12680
13303
|
let entries;
|
|
@@ -12700,7 +13323,7 @@ async function readFileInline(path) {
|
|
|
12700
13323
|
}
|
|
12701
13324
|
await walk(resolved);
|
|
12702
13325
|
if (files.length === 0) return void 0;
|
|
12703
|
-
const parts = await Promise.all(files.map((f) =>
|
|
13326
|
+
const parts = await Promise.all(files.map((f) => readFile12(f, "utf8").catch(() => "")));
|
|
12704
13327
|
return parts.filter(Boolean).join("\n\n");
|
|
12705
13328
|
}
|
|
12706
13329
|
function printFallbackInstructions(options) {
|
|
@@ -12725,6 +13348,23 @@ function printFallbackInstructions(options) {
|
|
|
12725
13348
|
function generatePropBuckets(component) {
|
|
12726
13349
|
return logPropBuckets("generate", [bucketComponentProps(component)]);
|
|
12727
13350
|
}
|
|
13351
|
+
function createCachedComponentResult(componentName, warnings = []) {
|
|
13352
|
+
return {
|
|
13353
|
+
componentName,
|
|
13354
|
+
classified: 0,
|
|
13355
|
+
excluded: 0,
|
|
13356
|
+
slots: 0,
|
|
13357
|
+
warnings,
|
|
13358
|
+
failed: false,
|
|
13359
|
+
cached: true,
|
|
13360
|
+
renamedSlotsCount: 0
|
|
13361
|
+
};
|
|
13362
|
+
}
|
|
13363
|
+
function writeCachedComponentStatus(position, componentName, pinned) {
|
|
13364
|
+
const status = pinned ? c.cyan("pinned (human-edited)") : c.green("cached");
|
|
13365
|
+
process.stderr.write(` ${position} ${c.bold(componentName)} ${status}
|
|
13366
|
+
`);
|
|
13367
|
+
}
|
|
12728
13368
|
async function showGenerateView(result) {
|
|
12729
13369
|
if (process.stdout.isTTY) {
|
|
12730
13370
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -12745,6 +13385,29 @@ session=${result.sessionId}
|
|
|
12745
13385
|
);
|
|
12746
13386
|
await exitWithAnalytics(0);
|
|
12747
13387
|
}
|
|
13388
|
+
function normalizeComponentForCache(component) {
|
|
13389
|
+
const slots = component.slots.map((slot, index, allSlots) => ({
|
|
13390
|
+
...slot,
|
|
13391
|
+
name: slot.name.trim() || (allSlots.length === 1 ? "children" : `slot_${index}`)
|
|
13392
|
+
}));
|
|
13393
|
+
return { ...component, slots };
|
|
13394
|
+
}
|
|
13395
|
+
function lookupComponentCache(db, component, promptHash) {
|
|
13396
|
+
const normalized = normalizeComponentForCache(component);
|
|
13397
|
+
const inputHash = hashComponentShape(normalized);
|
|
13398
|
+
const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
|
|
13399
|
+
if (cached) return cached;
|
|
13400
|
+
const legacyInputHash = hashComponentShape(component);
|
|
13401
|
+
return legacyInputHash === inputHash ? null : lookupCache(db, legacyInputHash, "component", component.component_id, promptHash);
|
|
13402
|
+
}
|
|
13403
|
+
function resolveComponentCache(db, component, promptHash, allowedComponentNames2) {
|
|
13404
|
+
const cached = lookupComponentCache(db, component, promptHash);
|
|
13405
|
+
if (cached && findUnknownSlotAllowedComponents(db, cached.sourceSessionId, allowedComponentNames2, component.component_id).length === 0) {
|
|
13406
|
+
return { entry: cached, humanEdited: cached.humanEdited };
|
|
13407
|
+
}
|
|
13408
|
+
const pinned = lookupCacheByEntity(db, "component", component.component_id);
|
|
13409
|
+
return pinned?.humanEdited && findUnknownSlotAllowedComponents(db, pinned.sourceSessionId, allowedComponentNames2, component.component_id).length === 0 ? { entry: pinned, humanEdited: true } : null;
|
|
13410
|
+
}
|
|
12748
13411
|
async function runOneComponent(options, component, index, total) {
|
|
12749
13412
|
const {
|
|
12750
13413
|
agent,
|
|
@@ -12754,10 +13417,13 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12754
13417
|
tokensInline,
|
|
12755
13418
|
tokenMapInline,
|
|
12756
13419
|
verbose,
|
|
13420
|
+
noCache,
|
|
12757
13421
|
skillPathOverride,
|
|
12758
13422
|
skillContentOverride,
|
|
13423
|
+
promptHash,
|
|
12759
13424
|
existingContentfulEntities,
|
|
12760
13425
|
existingTokensInline,
|
|
13426
|
+
precomputedCachedNames,
|
|
12761
13427
|
allowedComponentNames: allowedComponentNames2
|
|
12762
13428
|
} = options;
|
|
12763
13429
|
const pos = c.dim(`[${index + 1}/${total}]`);
|
|
@@ -12782,6 +13448,40 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12782
13448
|
allowedComponents: slot.allowedComponents.filter((name) => allowedComponentNames2.has(name))
|
|
12783
13449
|
};
|
|
12784
13450
|
});
|
|
13451
|
+
const cacheComponent = normalizeComponentForCache(component);
|
|
13452
|
+
if (!noCache && precomputedCachedNames.has(component.name)) {
|
|
13453
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13454
|
+
return createCachedComponentResult(component.name);
|
|
13455
|
+
}
|
|
13456
|
+
if (!noCache) {
|
|
13457
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13458
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13459
|
+
if (resolution && !resolution.humanEdited) {
|
|
13460
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13461
|
+
allowedComponentNames: allowedComponentNames2
|
|
13462
|
+
});
|
|
13463
|
+
storeCache(
|
|
13464
|
+
db,
|
|
13465
|
+
inputHash,
|
|
13466
|
+
"component",
|
|
13467
|
+
component.component_id,
|
|
13468
|
+
resolution.entry.sourceSessionId,
|
|
13469
|
+
resolution.entry.humanEdited,
|
|
13470
|
+
promptHash
|
|
13471
|
+
);
|
|
13472
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13473
|
+
return createCachedComponentResult(component.name);
|
|
13474
|
+
}
|
|
13475
|
+
if (resolution?.humanEdited) {
|
|
13476
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13477
|
+
allowedComponentNames: allowedComponentNames2
|
|
13478
|
+
});
|
|
13479
|
+
writeCachedComponentStatus(pos, component.name, true);
|
|
13480
|
+
return createCachedComponentResult(`${component.name}`, [
|
|
13481
|
+
`${component.name}: source changed but human edits preserved`
|
|
13482
|
+
]);
|
|
13483
|
+
}
|
|
13484
|
+
}
|
|
12785
13485
|
const rawComponentsInline = JSON.stringify(
|
|
12786
13486
|
[
|
|
12787
13487
|
{
|
|
@@ -12854,6 +13554,10 @@ ${outputBuf}`);
|
|
|
12854
13554
|
const applied = applyToolCalls(db, sessionId2, component.component_id, component.name, calls, warnings, {
|
|
12855
13555
|
allowedComponentNames: allowedComponentNames2
|
|
12856
13556
|
});
|
|
13557
|
+
if (!noCache) {
|
|
13558
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13559
|
+
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
13560
|
+
}
|
|
12857
13561
|
return {
|
|
12858
13562
|
componentName: component.name,
|
|
12859
13563
|
classified: applied.classified,
|
|
@@ -12905,7 +13609,7 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12905
13609
|
try {
|
|
12906
13610
|
const artifactsRoot = getRefineArtifactsRoot();
|
|
12907
13611
|
const paths = await getRefineSessionPaths(sessionId2, artifactsRoot);
|
|
12908
|
-
const raw = await
|
|
13612
|
+
const raw = await readFile12(paths.statePath, "utf8");
|
|
12909
13613
|
const snapshot = JSON.parse(raw);
|
|
12910
13614
|
const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
|
|
12911
13615
|
if (accepted.length === 0) return null;
|
|
@@ -12914,6 +13618,15 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12914
13618
|
return null;
|
|
12915
13619
|
}
|
|
12916
13620
|
}
|
|
13621
|
+
function parsePrecomputedCachedNames(value) {
|
|
13622
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
13623
|
+
try {
|
|
13624
|
+
const parsed = JSON.parse(value);
|
|
13625
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((name) => typeof name === "string") : []);
|
|
13626
|
+
} catch {
|
|
13627
|
+
return /* @__PURE__ */ new Set();
|
|
13628
|
+
}
|
|
13629
|
+
}
|
|
12917
13630
|
async function runGenerateSkill(skill, opts, verbose = false) {
|
|
12918
13631
|
const savedCreds = await readExperiencesCredentials();
|
|
12919
13632
|
const agentName = opts.agent ?? savedCreds.agent;
|
|
@@ -12942,8 +13655,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12942
13655
|
}
|
|
12943
13656
|
const generatePromptPath = generatePrompt === void 0 ? configuredGeneratePromptPath : void 0;
|
|
12944
13657
|
if (generatePromptPath) {
|
|
12945
|
-
if (!await pathExists(
|
|
12946
|
-
die(`Error: custom prompt path not found: ${
|
|
13658
|
+
if (!await pathExists(resolve12(generatePromptPath))) {
|
|
13659
|
+
die(`Error: custom prompt path not found: ${resolve12(generatePromptPath)}`);
|
|
12947
13660
|
}
|
|
12948
13661
|
if (!generatePromptPath.toLowerCase().endsWith(".md")) {
|
|
12949
13662
|
process.stderr.write(
|
|
@@ -12951,7 +13664,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12951
13664
|
`
|
|
12952
13665
|
);
|
|
12953
13666
|
}
|
|
12954
|
-
process.stderr.write(formatCustomPromptBanner("components",
|
|
13667
|
+
process.stderr.write(formatCustomPromptBanner("components", resolve12(generatePromptPath)));
|
|
12955
13668
|
}
|
|
12956
13669
|
if (skill === "tokens" && !opts.rawTokens) {
|
|
12957
13670
|
die("Error: --raw-tokens is required when using generate tokens");
|
|
@@ -12967,7 +13680,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12967
13680
|
let existingContentfulEntities;
|
|
12968
13681
|
let existingTokensInline;
|
|
12969
13682
|
if (opts.existingEntitiesPath) {
|
|
12970
|
-
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
13683
|
+
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(resolve12(opts.existingEntitiesPath));
|
|
12971
13684
|
if (existingContentfulEntities) {
|
|
12972
13685
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
12973
13686
|
} else {
|
|
@@ -13066,7 +13779,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13066
13779
|
rawComponentsInline: sampleInline ?? rawTokensInline,
|
|
13067
13780
|
propBucketsInline: sampleComponent ? generatePropBuckets(sampleComponent) : void 0,
|
|
13068
13781
|
rawTokensInline: skill === "tokens" ? rawTokensInline : void 0,
|
|
13069
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13782
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13070
13783
|
tokensInline,
|
|
13071
13784
|
tokenMapInline,
|
|
13072
13785
|
outDir: process.cwd(),
|
|
@@ -13092,7 +13805,64 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13092
13805
|
if (skill === "components" && allComponents && sessionId2) {
|
|
13093
13806
|
const db = openPipelineDb();
|
|
13094
13807
|
let componentResults;
|
|
13808
|
+
const precomputedCachedNames = parsePrecomputedCachedNames(opts.cachedComponents);
|
|
13095
13809
|
try {
|
|
13810
|
+
const existingContentfulEntitiesHashInputs = [];
|
|
13811
|
+
if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
|
|
13812
|
+
const promptHash = await hashPromptForSkill(
|
|
13813
|
+
"components",
|
|
13814
|
+
agent,
|
|
13815
|
+
model,
|
|
13816
|
+
generatePromptPath,
|
|
13817
|
+
existingContentfulEntitiesHashInputs,
|
|
13818
|
+
generatePrompt
|
|
13819
|
+
);
|
|
13820
|
+
if (opts.cacheStatus) {
|
|
13821
|
+
const cacheEnabled = opts.cache !== false && process.env.EDS_NO_CACHE !== "1";
|
|
13822
|
+
const cachedComponents = cacheEnabled ? allComponents.flatMap((component) => {
|
|
13823
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13824
|
+
return resolution ? [{ component, resolution }] : [];
|
|
13825
|
+
}) : [];
|
|
13826
|
+
if (cacheEnabled && opts.restoreCache) {
|
|
13827
|
+
const restorations = [];
|
|
13828
|
+
const rekeyed = [];
|
|
13829
|
+
const componentStatus = db.prepare(
|
|
13830
|
+
"SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?"
|
|
13831
|
+
);
|
|
13832
|
+
for (const { component, resolution } of cachedComponents) {
|
|
13833
|
+
const current = componentStatus.get(sessionId2, component.component_id);
|
|
13834
|
+
if (current?.status === "generated") continue;
|
|
13835
|
+
renameEmptySlots(db, sessionId2, component.component_id, component.name, component.slots.length);
|
|
13836
|
+
restorations.push({
|
|
13837
|
+
sourceSessionId: resolution.entry.sourceSessionId,
|
|
13838
|
+
targetSessionId: sessionId2,
|
|
13839
|
+
componentId: component.component_id
|
|
13840
|
+
});
|
|
13841
|
+
rekeyed.push({ component, cached: resolution.entry });
|
|
13842
|
+
}
|
|
13843
|
+
copyComponentsFromCache(db, restorations, { allowedComponentNames: allowedComponentNames2 });
|
|
13844
|
+
storeCaches(
|
|
13845
|
+
db,
|
|
13846
|
+
rekeyed.map(({ component, cached }) => ({
|
|
13847
|
+
inputHash: hashComponentShape(normalizeComponentForCache(component)),
|
|
13848
|
+
entityType: "component",
|
|
13849
|
+
entityId: component.component_id,
|
|
13850
|
+
sourceSessionId: cached.sourceSessionId,
|
|
13851
|
+
humanEdited: cached.humanEdited,
|
|
13852
|
+
promptHash
|
|
13853
|
+
}))
|
|
13854
|
+
);
|
|
13855
|
+
}
|
|
13856
|
+
const fullyCached = cacheEnabled && cachedComponents.length === allComponents.length;
|
|
13857
|
+
process.stdout.write(`cache-status=${fullyCached ? "hit" : "miss"}
|
|
13858
|
+
`);
|
|
13859
|
+
process.stdout.write(
|
|
13860
|
+
`cache-components=${JSON.stringify(cachedComponents.map(({ component }) => component.name))}
|
|
13861
|
+
`
|
|
13862
|
+
);
|
|
13863
|
+
await exitWithAnalytics(0);
|
|
13864
|
+
return;
|
|
13865
|
+
}
|
|
13096
13866
|
componentResults = await runAllComponents(
|
|
13097
13867
|
{
|
|
13098
13868
|
agent,
|
|
@@ -13102,10 +13872,13 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13102
13872
|
tokensInline,
|
|
13103
13873
|
tokenMapInline,
|
|
13104
13874
|
verbose,
|
|
13875
|
+
noCache: opts.cache === false || process.env.EDS_NO_CACHE === "1",
|
|
13105
13876
|
skillPathOverride: generatePromptPath,
|
|
13106
13877
|
skillContentOverride: generatePrompt,
|
|
13878
|
+
promptHash,
|
|
13107
13879
|
existingContentfulEntities,
|
|
13108
13880
|
existingTokensInline,
|
|
13881
|
+
precomputedCachedNames,
|
|
13109
13882
|
allowedComponentNames: allowedComponentNames2
|
|
13110
13883
|
},
|
|
13111
13884
|
allComponents
|
|
@@ -13114,7 +13887,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13114
13887
|
db.close();
|
|
13115
13888
|
}
|
|
13116
13889
|
const failed = componentResults.filter((r) => r.failed);
|
|
13117
|
-
const
|
|
13890
|
+
const cachedResults = componentResults.filter((r) => r.cached);
|
|
13891
|
+
const generated = componentResults.filter((r) => !r.failed && !r.cached);
|
|
13118
13892
|
const allWarnings = componentResults.flatMap((r) => r.warnings.map((w) => ` ${r.componentName}: ${w}`));
|
|
13119
13893
|
if (allWarnings.length > 0) {
|
|
13120
13894
|
process.stderr.write(c.yellow("Warnings:") + "\n" + allWarnings.join("\n") + "\n");
|
|
@@ -13130,17 +13904,21 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13130
13904
|
const totalExcluded = generated.reduce((s, r) => s + r.excluded, 0);
|
|
13131
13905
|
const totalRenamedSlots = componentResults.reduce((s, r) => s + r.renamedSlotsCount, 0);
|
|
13132
13906
|
const allOk = failed.length === 0;
|
|
13907
|
+
const cachedNote = cachedResults.length > 0 ? c.dim(` (${cachedResults.length} cached)`) : "";
|
|
13133
13908
|
process.stderr.write(
|
|
13134
|
-
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length}/${componentResults.length} components` + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13909
|
+
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length + cachedResults.length}/${componentResults.length} components` + cachedNote + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13135
13910
|
);
|
|
13136
13911
|
process.stdout.write(`renamed-slots: ${totalRenamedSlots}
|
|
13137
13912
|
`);
|
|
13138
|
-
if (generated.length === 0) {
|
|
13913
|
+
if (generated.length === 0 && cachedResults.length === 0) {
|
|
13139
13914
|
die(
|
|
13140
13915
|
`Error: all ${componentResults.length} component(s) failed to generate \u2014 see the per-component errors above.`
|
|
13141
13916
|
);
|
|
13142
13917
|
}
|
|
13143
13918
|
} else if (skill === "tokens") {
|
|
13919
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
13920
|
+
const tokenInputContent = rawTokensInline ?? "";
|
|
13921
|
+
const tokenInputHash = hashTokenContent(tokenInputContent);
|
|
13144
13922
|
const db = openPipelineDb();
|
|
13145
13923
|
try {
|
|
13146
13924
|
let resolvedSessionId = opts.session;
|
|
@@ -13167,11 +13945,26 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13167
13945
|
}
|
|
13168
13946
|
sessionId2 = resolvedSessionId;
|
|
13169
13947
|
await bindAnalyticsSessionId(resolvedSessionId);
|
|
13948
|
+
const tokenPromptHash = await hashPromptForSkill("tokens", agent, model);
|
|
13949
|
+
if (!noCache) {
|
|
13950
|
+
const tokenCached = lookupCache(db, tokenInputHash, "token_set", "__tokens__", tokenPromptHash);
|
|
13951
|
+
if (tokenCached) {
|
|
13952
|
+
copyTokensFromCache(db, tokenCached.sourceSessionId, resolvedSessionId);
|
|
13953
|
+
sessionId2 = resolvedSessionId;
|
|
13954
|
+
process.stderr.write(
|
|
13955
|
+
`Done: tokens reused from cache ${c.dim(`(source: ${tokenCached.sourceSessionId.slice(0, 12)})`)}
|
|
13956
|
+
`
|
|
13957
|
+
);
|
|
13958
|
+
db.close();
|
|
13959
|
+
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13960
|
+
return;
|
|
13961
|
+
}
|
|
13962
|
+
}
|
|
13170
13963
|
const prompt = await buildPrompt({
|
|
13171
13964
|
skill,
|
|
13172
13965
|
mode: "autonomous",
|
|
13173
13966
|
rawTokensInline,
|
|
13174
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13967
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13175
13968
|
tokensInline,
|
|
13176
13969
|
tokenMapInline,
|
|
13177
13970
|
outDir: process.cwd()
|
|
@@ -13208,6 +14001,9 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13208
14001
|
`);
|
|
13209
14002
|
}
|
|
13210
14003
|
applyTokenToolCalls(db, resolvedSessionId, tokenCalls, []);
|
|
14004
|
+
if (!noCache) {
|
|
14005
|
+
storeCache(db, tokenInputHash, "token_set", "__tokens__", resolvedSessionId, false, tokenPromptHash);
|
|
14006
|
+
}
|
|
13211
14007
|
sessionId2 = resolvedSessionId;
|
|
13212
14008
|
const groupCount = tokenCalls.filter((tc) => tc.tool === "set_group").length;
|
|
13213
14009
|
process.stderr.write(`Done: ${tokenCount} tokens, ${groupCount} groups stored
|
|
@@ -13219,7 +14015,10 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13219
14015
|
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13220
14016
|
}
|
|
13221
14017
|
function addAgentFlags(cmd) {
|
|
13222
|
-
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent")
|
|
14018
|
+
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent").option(
|
|
14019
|
+
"--no-cache",
|
|
14020
|
+
"Bypass ALL fine-grained caches (extract, select, generate) and force AI re-run. Cache keys now factor in prompt content \u2014 changing the prompt file via --generate-prompt-path or --select-prompt-path will already bust the corresponding stage. Use --no-cache to force a full re-run."
|
|
14021
|
+
);
|
|
13223
14022
|
}
|
|
13224
14023
|
function registerInternalGenerateCommand(program) {
|
|
13225
14024
|
const generate = program.command("__generate", { hidden: true }).description("Internal import pipeline generation command");
|
|
@@ -13235,6 +14034,12 @@ function registerInternalGenerateCommand(program) {
|
|
|
13235
14034
|
"--existing-entities-path <path>",
|
|
13236
14035
|
"Path to the .existing-entities.json file written after CMA credentials are supplied. When present, per-component prompts include a summary of the target space so classifications can align to existing prop names/tokens. Missing/malformed files are treated as no-op."
|
|
13237
14036
|
);
|
|
14037
|
+
componentsCmd.option("--cache-status", "Check whether all selected component definitions are cached");
|
|
14038
|
+
componentsCmd.option("--restore-cache", "Restore cached component definitions into the current session");
|
|
14039
|
+
componentsCmd.option(
|
|
14040
|
+
"--cached-components <json>",
|
|
14041
|
+
"Component names already restored by a prior cache-status lookup; skip per-component cache lookup"
|
|
14042
|
+
);
|
|
13238
14043
|
addAgentFlags(componentsCmd).action(async (opts) => {
|
|
13239
14044
|
await runGenerateSkill("components", opts, opts.verbose ?? false);
|
|
13240
14045
|
});
|
|
@@ -13262,6 +14067,7 @@ var init_command = __esm({
|
|
|
13262
14067
|
init_agent_output();
|
|
13263
14068
|
init_GenerateView();
|
|
13264
14069
|
init_db();
|
|
14070
|
+
init_cache_keys();
|
|
13265
14071
|
init_read_existing_contentful_entities_from_session();
|
|
13266
14072
|
init_summarize_existing_contentful_entities();
|
|
13267
14073
|
init_resolve_session_id();
|
|
@@ -13977,7 +14783,7 @@ var init_user_agent = __esm({
|
|
|
13977
14783
|
// packages/experience-design-system-cli-legacy/src/apply/api-client.ts
|
|
13978
14784
|
import { parseCDFComponents } from "@contentful/experience-design-system-types";
|
|
13979
14785
|
function defaultSleep(delayMs) {
|
|
13980
|
-
return new Promise((
|
|
14786
|
+
return new Promise((resolve21) => setTimeout(resolve21, delayMs));
|
|
13981
14787
|
}
|
|
13982
14788
|
function isTransientStatus(status) {
|
|
13983
14789
|
return status >= 500 && status <= 599;
|
|
@@ -14367,7 +15173,7 @@ ${trimmed}`;
|
|
|
14367
15173
|
const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
|
|
14368
15174
|
const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
|
|
14369
15175
|
const jitter = Math.random() * baseDelay * 0.15;
|
|
14370
|
-
await new Promise((
|
|
15176
|
+
await new Promise((resolve21) => setTimeout(resolve21, baseDelay + jitter));
|
|
14371
15177
|
}
|
|
14372
15178
|
}
|
|
14373
15179
|
throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
|
|
@@ -15177,7 +15983,7 @@ var init_terminal_capabilities = __esm({
|
|
|
15177
15983
|
|
|
15178
15984
|
// packages/experience-design-system-cli-legacy/src/apply/command.ts
|
|
15179
15985
|
import { createElement as createElement2 } from "react";
|
|
15180
|
-
import { readFile as
|
|
15986
|
+
import { readFile as readFile13, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
15181
15987
|
import { join as join16 } from "node:path";
|
|
15182
15988
|
import {
|
|
15183
15989
|
validateCDF,
|
|
@@ -15198,7 +16004,7 @@ function dieWithApiError(error) {
|
|
|
15198
16004
|
async function readJsonFile(flag, p) {
|
|
15199
16005
|
let text;
|
|
15200
16006
|
try {
|
|
15201
|
-
text = await
|
|
16007
|
+
text = await readFile13(p, "utf8");
|
|
15202
16008
|
} catch {
|
|
15203
16009
|
return await die2(`Error: file not found: ${p} (from ${flag})`);
|
|
15204
16010
|
}
|
|
@@ -15252,7 +16058,7 @@ async function readTokensFromPath(flag, p) {
|
|
|
15252
16058
|
for (const file of files.sort()) {
|
|
15253
16059
|
let text;
|
|
15254
16060
|
try {
|
|
15255
|
-
text = await
|
|
16061
|
+
text = await readFile13(file, "utf8");
|
|
15256
16062
|
} catch {
|
|
15257
16063
|
continue;
|
|
15258
16064
|
}
|
|
@@ -15621,11 +16427,11 @@ var init_command2 = __esm({
|
|
|
15621
16427
|
});
|
|
15622
16428
|
|
|
15623
16429
|
// packages/experience-design-system-cli-legacy/src/print/validate/validators/read-json-file.ts
|
|
15624
|
-
import { readFile as
|
|
16430
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
15625
16431
|
async function readJsonFile2(filePath) {
|
|
15626
16432
|
let content;
|
|
15627
16433
|
try {
|
|
15628
|
-
content = await
|
|
16434
|
+
content = await readFile14(filePath, "utf-8");
|
|
15629
16435
|
} catch (err) {
|
|
15630
16436
|
return {
|
|
15631
16437
|
ok: false,
|
|
@@ -16036,7 +16842,7 @@ var init_ValidateView = __esm({
|
|
|
16036
16842
|
// packages/experience-design-system-cli-legacy/src/print/command.ts
|
|
16037
16843
|
import { createElement as createElement3 } from "react";
|
|
16038
16844
|
import { access as access3, mkdir as mkdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
16039
|
-
import { basename as basename5, resolve as
|
|
16845
|
+
import { basename as basename5, resolve as resolve13 } from "node:path";
|
|
16040
16846
|
import { CDF_SCHEMA_URL } from "@contentful/experience-design-system-types";
|
|
16041
16847
|
async function die3(message) {
|
|
16042
16848
|
process.stderr.write(`${message}
|
|
@@ -16103,7 +16909,7 @@ function registerPrintCommand(program) {
|
|
|
16103
16909
|
"--allow-empty",
|
|
16104
16910
|
"Write an empty-but-present CDF file when no components are accepted (a subsequent push then removes ALL components from the target space). Without this, an empty accepted set is an error."
|
|
16105
16911
|
).action(async (opts) => {
|
|
16106
|
-
const outPath =
|
|
16912
|
+
const outPath = resolve13(opts.out);
|
|
16107
16913
|
await assertOutIsNotDirectory(outPath);
|
|
16108
16914
|
const sessionId2 = await resolveSession(opts.session, "generate components");
|
|
16109
16915
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16151,7 +16957,7 @@ function registerPrintCommand(program) {
|
|
|
16151
16957
|
`
|
|
16152
16958
|
);
|
|
16153
16959
|
}
|
|
16154
|
-
await mkdir3(
|
|
16960
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16155
16961
|
await writeFile3(outPath, `${JSON.stringify(cdfObj, null, 2)}
|
|
16156
16962
|
`);
|
|
16157
16963
|
process.stdout.write(
|
|
@@ -16160,7 +16966,7 @@ function registerPrintCommand(program) {
|
|
|
16160
16966
|
);
|
|
16161
16967
|
});
|
|
16162
16968
|
print.command("tokens").description("Write generated tokens to a DTCG JSON file").option("--session <id>", "Session ID to print from (default: most recent generate tokens session)").option("--out <path>", "Output file path", "tokens.json").action(async (opts) => {
|
|
16163
|
-
const outPath =
|
|
16969
|
+
const outPath = resolve13(opts.out);
|
|
16164
16970
|
await assertOutIsNotDirectory(outPath);
|
|
16165
16971
|
const sessionId2 = await resolveSession(opts.session, "generate tokens");
|
|
16166
16972
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16175,7 +16981,7 @@ function registerPrintCommand(program) {
|
|
|
16175
16981
|
await die3(`Error: no generated tokens in session '${sessionId2}'. Run generate tokens first.`);
|
|
16176
16982
|
}
|
|
16177
16983
|
const tree = rebuildDTCGTree(result.groups, result.tokens);
|
|
16178
|
-
await mkdir3(
|
|
16984
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16179
16985
|
await writeFile3(outPath, `${JSON.stringify(tree, null, 2)}
|
|
16180
16986
|
`);
|
|
16181
16987
|
process.stdout.write(
|
|
@@ -16324,7 +17130,7 @@ function MapTokensView({ result, onExit }) {
|
|
|
16324
17130
|
const timer = setTimeout(onExit, 100);
|
|
16325
17131
|
return () => clearTimeout(timer);
|
|
16326
17132
|
}, [onExit]);
|
|
16327
|
-
const summary = `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
17133
|
+
const summary = result.cached ? "reused from cache" : `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
16328
17134
|
return /* @__PURE__ */ jsx8(
|
|
16329
17135
|
CommandCompletionView,
|
|
16330
17136
|
{
|
|
@@ -16458,8 +17264,8 @@ var init_resolve_defaults = __esm({
|
|
|
16458
17264
|
|
|
16459
17265
|
// packages/experience-design-system-cli-legacy/src/map-tokens/command.ts
|
|
16460
17266
|
import { createElement as createElement4 } from "react";
|
|
16461
|
-
import { readFile as
|
|
16462
|
-
import { resolve as
|
|
17267
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
17268
|
+
import { resolve as resolve14 } from "node:path";
|
|
16463
17269
|
async function renderResult(result) {
|
|
16464
17270
|
if (process.stdout.isTTY) {
|
|
16465
17271
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -16467,13 +17273,12 @@ async function renderResult(result) {
|
|
|
16467
17273
|
);
|
|
16468
17274
|
await waitUntilExit();
|
|
16469
17275
|
} else {
|
|
16470
|
-
|
|
16471
|
-
|
|
17276
|
+
const summary = result.cached ? "cached" : `${result.applied} mapping(s) applied`;
|
|
17277
|
+
process.stdout.write(`map tokens complete
|
|
16472
17278
|
agent: ${result.agent}
|
|
16473
17279
|
session=${result.sessionId}
|
|
16474
|
-
${
|
|
16475
|
-
`
|
|
16476
|
-
);
|
|
17280
|
+
${summary}
|
|
17281
|
+
`);
|
|
16477
17282
|
await exitWithAnalytics(0);
|
|
16478
17283
|
}
|
|
16479
17284
|
}
|
|
@@ -16495,7 +17300,7 @@ async function runMapTokens(opts) {
|
|
|
16495
17300
|
let mapPromptPath;
|
|
16496
17301
|
if (mapPromptOverride?.kind === "text") mapPromptText = mapPromptOverride.value;
|
|
16497
17302
|
if (mapPromptOverride?.kind === "path") {
|
|
16498
|
-
mapPromptPath =
|
|
17303
|
+
mapPromptPath = resolve14(mapPromptOverride.value);
|
|
16499
17304
|
try {
|
|
16500
17305
|
await resolvePromptOverride(mapPromptOverride);
|
|
16501
17306
|
} catch (error) {
|
|
@@ -16515,7 +17320,7 @@ async function runMapTokens(opts) {
|
|
|
16515
17320
|
const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
|
|
16516
17321
|
const tokenMapDiagnostics = [];
|
|
16517
17322
|
if (opts.tokenMap) {
|
|
16518
|
-
const fileMappings = JSON.parse(await
|
|
17323
|
+
const fileMappings = JSON.parse(await readFile15(opts.tokenMap, "utf8"));
|
|
16519
17324
|
const validMappings = {};
|
|
16520
17325
|
for (const [rawName, path] of Object.entries(fileMappings)) {
|
|
16521
17326
|
if (knownTokenPaths.has(path)) {
|
|
@@ -16593,7 +17398,7 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16593
17398
|
let existingTokensInline;
|
|
16594
17399
|
if (opts.existingEntitiesPath) {
|
|
16595
17400
|
const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
16596
|
-
|
|
17401
|
+
resolve14(opts.existingEntitiesPath)
|
|
16597
17402
|
);
|
|
16598
17403
|
if (existingContentfulEntities) {
|
|
16599
17404
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
@@ -16628,10 +17433,30 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16628
17433
|
skipAgent: "true"
|
|
16629
17434
|
});
|
|
16630
17435
|
updateStep(db, stepId2, "complete", { applied: "0", skipAgent: "true" });
|
|
16631
|
-
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0 });
|
|
17436
|
+
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0, cached: false });
|
|
16632
17437
|
return;
|
|
16633
17438
|
}
|
|
16634
17439
|
const agent = configuredAgent;
|
|
17440
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
17441
|
+
const promptHash = await hashPromptForSkill(
|
|
17442
|
+
"map-tokens",
|
|
17443
|
+
agent,
|
|
17444
|
+
model,
|
|
17445
|
+
void 0,
|
|
17446
|
+
existingTokensInline ? [hashContent(existingTokensInline)] : [],
|
|
17447
|
+
mapPromptText
|
|
17448
|
+
);
|
|
17449
|
+
const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
|
|
17450
|
+
if (!noCache) {
|
|
17451
|
+
const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
|
|
17452
|
+
if (cached) {
|
|
17453
|
+
const appliedFromCache = copyMapTokensFromCache(db, cached.sourceSessionId, sessionId2);
|
|
17454
|
+
const stepId2 = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
|
|
17455
|
+
updateStep(db, stepId2, "complete", { cached: "true", applied: String(appliedFromCache) });
|
|
17456
|
+
await renderResult({ agent, sessionId: sessionId2, applied: appliedFromCache, cached: true });
|
|
17457
|
+
return;
|
|
17458
|
+
}
|
|
17459
|
+
}
|
|
16635
17460
|
const binary = resolveAgentBinary(agent);
|
|
16636
17461
|
if (!await assertBinaryInPath(binary)) {
|
|
16637
17462
|
die(
|
|
@@ -16651,20 +17476,23 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
16651
17476
|
}
|
|
16652
17477
|
const { calls, warnings: parseWarnings } = parseMapTokenPropToolCallLines(result.stdout);
|
|
16653
17478
|
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, calls, parseWarnings);
|
|
17479
|
+
if (!noCache) {
|
|
17480
|
+
storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId2, false, promptHash);
|
|
17481
|
+
}
|
|
16654
17482
|
updateStep(db, stepId, "complete", { applied: String(applied), warnings: String(warnings.length) });
|
|
16655
17483
|
if (warnings.length > 0) {
|
|
16656
17484
|
process.stderr.write(`Warnings:
|
|
16657
17485
|
${warnings.map((w) => ` ${w}`).join("\n")}
|
|
16658
17486
|
`);
|
|
16659
17487
|
}
|
|
16660
|
-
await renderResult({ agent, sessionId: sessionId2, applied });
|
|
17488
|
+
await renderResult({ agent, sessionId: sessionId2, applied, cached: false });
|
|
16661
17489
|
} finally {
|
|
16662
17490
|
db.close();
|
|
16663
17491
|
}
|
|
16664
17492
|
}
|
|
16665
17493
|
function registerMapTokensCommand(program) {
|
|
16666
17494
|
const map = program.command("map", { hidden: true }).description("Suggest token restrictions for generated design-token props");
|
|
16667
|
-
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option(
|
|
17495
|
+
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option("--no-cache", "Bypass the map-tokens cache and force a re-run").option(
|
|
16668
17496
|
"--prompt <stage=value>",
|
|
16669
17497
|
"Override a stage prompt (repeatable). Used here for the map-tokens stage.",
|
|
16670
17498
|
(v, acc) => [...acc, v],
|
|
@@ -16684,6 +17512,7 @@ var init_command4 = __esm({
|
|
|
16684
17512
|
init_render_with_goodbye();
|
|
16685
17513
|
init_src();
|
|
16686
17514
|
init_db();
|
|
17515
|
+
init_cache_keys();
|
|
16687
17516
|
init_read_existing_contentful_entities_from_session();
|
|
16688
17517
|
init_summarize_existing_contentful_entities();
|
|
16689
17518
|
init_command3();
|
|
@@ -16700,7 +17529,7 @@ var init_command4 = __esm({
|
|
|
16700
17529
|
});
|
|
16701
17530
|
|
|
16702
17531
|
// packages/experience-design-system-cli-legacy/src/import/path-utils.ts
|
|
16703
|
-
import { resolve as
|
|
17532
|
+
import { resolve as resolve15 } from "node:path";
|
|
16704
17533
|
import { homedir as homedir5 } from "node:os";
|
|
16705
17534
|
function expandTilde(input) {
|
|
16706
17535
|
if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
|
|
@@ -16714,7 +17543,7 @@ function normalizePath(input) {
|
|
|
16714
17543
|
p = p.slice(1, -1);
|
|
16715
17544
|
}
|
|
16716
17545
|
p = expandTilde(p);
|
|
16717
|
-
return
|
|
17546
|
+
return resolve15(p);
|
|
16718
17547
|
}
|
|
16719
17548
|
var init_path_utils = __esm({
|
|
16720
17549
|
"packages/experience-design-system-cli-legacy/src/import/path-utils.ts"() {
|
|
@@ -16939,7 +17768,7 @@ var init_save_path_resolver = __esm({
|
|
|
16939
17768
|
});
|
|
16940
17769
|
|
|
16941
17770
|
// packages/experience-design-system-cli-legacy/src/runs/store.ts
|
|
16942
|
-
import { readFile as
|
|
17771
|
+
import { readFile as readFile16, writeFile as writeFile4, mkdir as mkdir4, rename } from "node:fs/promises";
|
|
16943
17772
|
import { join as join20 } from "node:path";
|
|
16944
17773
|
import { homedir as homedir6 } from "node:os";
|
|
16945
17774
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -16979,7 +17808,7 @@ function migrateRecord(rec) {
|
|
|
16979
17808
|
}
|
|
16980
17809
|
async function readFileMaybe() {
|
|
16981
17810
|
try {
|
|
16982
|
-
const raw = await
|
|
17811
|
+
const raw = await readFile16(RUNS_PATH, "utf8");
|
|
16983
17812
|
const parsed = JSON.parse(raw);
|
|
16984
17813
|
if (!READABLE_VERSIONS.has(parsed.version)) {
|
|
16985
17814
|
throw new Error(
|
|
@@ -17043,15 +17872,15 @@ var init_store = __esm({
|
|
|
17043
17872
|
});
|
|
17044
17873
|
|
|
17045
17874
|
// packages/experience-design-system-cli-legacy/src/runs/fingerprint.ts
|
|
17046
|
-
import { createHash as
|
|
17047
|
-
import { readFile as
|
|
17048
|
-
import { resolve as
|
|
17875
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
17876
|
+
import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
|
|
17877
|
+
import { resolve as resolve16 } from "node:path";
|
|
17049
17878
|
function rowField(row, key) {
|
|
17050
17879
|
const v = row[key];
|
|
17051
17880
|
return typeof v === "string" ? v : null;
|
|
17052
17881
|
}
|
|
17053
17882
|
function sha256Hex(buf) {
|
|
17054
|
-
return
|
|
17883
|
+
return createHash6("sha256").update(buf).digest("hex");
|
|
17055
17884
|
}
|
|
17056
17885
|
async function buildSourceFingerprint(opts) {
|
|
17057
17886
|
const rows = opts.db.prepare("SELECT name, source_path FROM raw_components WHERE session_id = ?").all(opts.extractSessionId);
|
|
@@ -17061,7 +17890,7 @@ async function buildSourceFingerprint(opts) {
|
|
|
17061
17890
|
const sourcePath = rowField(row, "source_path");
|
|
17062
17891
|
const name = rowField(row, "name");
|
|
17063
17892
|
if (!sourcePath) continue;
|
|
17064
|
-
const abs =
|
|
17893
|
+
const abs = resolve16(sourcePath);
|
|
17065
17894
|
if (seen.has(abs)) continue;
|
|
17066
17895
|
seen.add(abs);
|
|
17067
17896
|
try {
|
|
@@ -17076,10 +17905,10 @@ async function buildSourceFingerprint(opts) {
|
|
|
17076
17905
|
let rawTokensMtime = null;
|
|
17077
17906
|
let rawTokensContentHash = null;
|
|
17078
17907
|
if (opts.rawTokensPath) {
|
|
17079
|
-
const abs =
|
|
17908
|
+
const abs = resolve16(opts.rawTokensPath);
|
|
17080
17909
|
rawTokensPath = abs;
|
|
17081
17910
|
try {
|
|
17082
|
-
const [st, buf] = await Promise.all([stat4(abs),
|
|
17911
|
+
const [st, buf] = await Promise.all([stat4(abs), readFile17(abs)]);
|
|
17083
17912
|
rawTokensMtime = st.mtime.toISOString();
|
|
17084
17913
|
rawTokensContentHash = sha256Hex(buf);
|
|
17085
17914
|
} catch {
|
|
@@ -18834,11 +19663,11 @@ var init_slot_graph = __esm({
|
|
|
18834
19663
|
});
|
|
18835
19664
|
|
|
18836
19665
|
// packages/experience-design-system-cli-legacy/src/analyze/select/parser.ts
|
|
18837
|
-
import { createHash as
|
|
19666
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
18838
19667
|
import { access as access5 } from "node:fs/promises";
|
|
18839
|
-
import { isAbsolute, relative, resolve as
|
|
19668
|
+
import { isAbsolute, relative, resolve as resolve17 } from "node:path";
|
|
18840
19669
|
function createComponentId(name, resolvedSourcePath) {
|
|
18841
|
-
const sourceHash =
|
|
19670
|
+
const sourceHash = createHash7("sha256").update(`${name}:${resolvedSourcePath}`).digest("hex").slice(0, 12);
|
|
18842
19671
|
return `${name}-${sourceHash}`;
|
|
18843
19672
|
}
|
|
18844
19673
|
async function resolveComponentSourcePath(source, reviewRoot) {
|
|
@@ -18850,7 +19679,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18850
19679
|
throw new Error(`Unable to access component source at ${source}`);
|
|
18851
19680
|
}
|
|
18852
19681
|
}
|
|
18853
|
-
const candidate =
|
|
19682
|
+
const candidate = resolve17(reviewRoot, source);
|
|
18854
19683
|
const relativeToRoot = relative(reviewRoot, candidate);
|
|
18855
19684
|
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || isAbsolute(relativeToRoot)) {
|
|
18856
19685
|
throw new Error(
|
|
@@ -18865,7 +19694,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18865
19694
|
}
|
|
18866
19695
|
}
|
|
18867
19696
|
async function loadReviewInput(components, options = {}) {
|
|
18868
|
-
const reviewRoot =
|
|
19697
|
+
const reviewRoot = resolve17(options.reviewRoot ?? process.cwd());
|
|
18869
19698
|
const records = await Promise.all(
|
|
18870
19699
|
components.map(async (component) => {
|
|
18871
19700
|
let resolvedSourcePath;
|
|
@@ -18896,7 +19725,7 @@ var init_parser = __esm({
|
|
|
18896
19725
|
});
|
|
18897
19726
|
|
|
18898
19727
|
// packages/experience-design-system-cli-legacy/src/analyze/select/command.ts
|
|
18899
|
-
import { access as access6, readFile as
|
|
19728
|
+
import { access as access6, readFile as readFile18 } from "node:fs/promises";
|
|
18900
19729
|
async function loadAndValidateForReview(sessionId2, projectRoot) {
|
|
18901
19730
|
const db = openPipelineDb();
|
|
18902
19731
|
let rawComponents;
|
|
@@ -18914,7 +19743,7 @@ async function patchReviewStateWithValidationErrors(sessionId2, errors, opts = {
|
|
|
18914
19743
|
let snapshot;
|
|
18915
19744
|
try {
|
|
18916
19745
|
await access6(paths.statePath);
|
|
18917
|
-
snapshot = JSON.parse(await
|
|
19746
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18918
19747
|
} catch {
|
|
18919
19748
|
snapshot = await loadAndValidateForReview(sessionId2, void 0);
|
|
18920
19749
|
snapshot = await ensureRefineSession(sessionId2, artifactsRoot, snapshot);
|
|
@@ -18965,7 +19794,7 @@ async function rejectComponentsByName(sessionId2, names, opts = {}) {
|
|
|
18965
19794
|
const nameSet = new Set(names);
|
|
18966
19795
|
let snapshot;
|
|
18967
19796
|
try {
|
|
18968
|
-
snapshot = JSON.parse(await
|
|
19797
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18969
19798
|
} catch {
|
|
18970
19799
|
return;
|
|
18971
19800
|
}
|
|
@@ -19064,9 +19893,9 @@ function spawnGenerateChild(opts) {
|
|
|
19064
19893
|
stderr += chunk;
|
|
19065
19894
|
opts.onStderr?.(chunk);
|
|
19066
19895
|
});
|
|
19067
|
-
const donePromise = new Promise((
|
|
19896
|
+
const donePromise = new Promise((resolve21) => {
|
|
19068
19897
|
child.on("close", (code, signal) => {
|
|
19069
|
-
|
|
19898
|
+
resolve21({
|
|
19070
19899
|
exitCode: code ?? 0,
|
|
19071
19900
|
signal: signal ?? null,
|
|
19072
19901
|
stdout,
|
|
@@ -19074,7 +19903,7 @@ function spawnGenerateChild(opts) {
|
|
|
19074
19903
|
});
|
|
19075
19904
|
});
|
|
19076
19905
|
child.on("error", (err) => {
|
|
19077
|
-
|
|
19906
|
+
resolve21({
|
|
19078
19907
|
exitCode: 1,
|
|
19079
19908
|
signal: null,
|
|
19080
19909
|
stdout,
|
|
@@ -27212,6 +28041,9 @@ function shouldGenerateAfterCredentialsValidated(opts) {
|
|
|
27212
28041
|
function shouldSkipFinalReviewAfterCredentials(state) {
|
|
27213
28042
|
return state.finalReviewPassed && state.generateSessionId != null;
|
|
27214
28043
|
}
|
|
28044
|
+
function resolveNoCacheForGenerate(opts) {
|
|
28045
|
+
return opts.cliNoCache;
|
|
28046
|
+
}
|
|
27215
28047
|
function shouldBypassPreview(state) {
|
|
27216
28048
|
return state.credentialsSkipped === true;
|
|
27217
28049
|
}
|
|
@@ -27238,39 +28070,66 @@ var init_wizard_state_transitions = __esm({
|
|
|
27238
28070
|
async function runSelectionAgent(options) {
|
|
27239
28071
|
const db = openPipelineDb();
|
|
27240
28072
|
let components;
|
|
28073
|
+
const cachedDecisions = /* @__PURE__ */ new Map();
|
|
28074
|
+
const cliVersion2 = await getCliCacheVersion();
|
|
28075
|
+
const promptHash = await hashPromptForSkill(
|
|
28076
|
+
"select",
|
|
28077
|
+
options.agent,
|
|
28078
|
+
options.model,
|
|
28079
|
+
options.promptPath,
|
|
28080
|
+
[SELECT_PAYLOAD_FORMAT],
|
|
28081
|
+
options.promptText
|
|
28082
|
+
);
|
|
27241
28083
|
try {
|
|
27242
28084
|
components = loadRawComponents(db, options.sessionId);
|
|
28085
|
+
if (!options.noCache) {
|
|
28086
|
+
for (const component of components) {
|
|
28087
|
+
const componentHash = hashComponentShape(component);
|
|
28088
|
+
const cached = lookupSelectCache(db, componentHash, promptHash, cliVersion2);
|
|
28089
|
+
if (cached) {
|
|
28090
|
+
cachedDecisions.set(component.name, {
|
|
28091
|
+
decision: cached.decision,
|
|
28092
|
+
reason: cached.reason
|
|
28093
|
+
});
|
|
28094
|
+
}
|
|
28095
|
+
}
|
|
28096
|
+
}
|
|
27243
28097
|
} finally {
|
|
27244
28098
|
db.close();
|
|
27245
28099
|
}
|
|
27246
28100
|
if (components.length === 0) return;
|
|
27247
|
-
const
|
|
27248
|
-
|
|
27249
|
-
|
|
27250
|
-
|
|
27251
|
-
|
|
27252
|
-
|
|
27253
|
-
|
|
27254
|
-
|
|
27255
|
-
|
|
27256
|
-
|
|
27257
|
-
|
|
27258
|
-
|
|
27259
|
-
|
|
27260
|
-
|
|
27261
|
-
|
|
27262
|
-
|
|
27263
|
-
|
|
27264
|
-
|
|
27265
|
-
|
|
27266
|
-
|
|
27267
|
-
|
|
27268
|
-
|
|
27269
|
-
|
|
27270
|
-
|
|
27271
|
-
|
|
28101
|
+
const componentsToRun = components.filter((component) => !cachedDecisions.has(component.name));
|
|
28102
|
+
let calls = [];
|
|
28103
|
+
if (componentsToRun.length > 0) {
|
|
28104
|
+
const invoker2 = createLocalCliAgentInvoker({
|
|
28105
|
+
onDebugEvent: (name, payload) => getDebugLogger().event("agent", name, payload)
|
|
28106
|
+
});
|
|
28107
|
+
const prompt = await buildPrompt({
|
|
28108
|
+
skill: "select",
|
|
28109
|
+
mode: "autonomous",
|
|
28110
|
+
rawComponentsInline: JSON.stringify(
|
|
28111
|
+
componentsToRun.map((component) => ({ ...component, props: component.props.map(stripPropProvenance) })),
|
|
28112
|
+
null,
|
|
28113
|
+
2
|
|
28114
|
+
),
|
|
28115
|
+
propBucketsInline: logPropBuckets("select", bucketComponentsProps(componentsToRun)),
|
|
28116
|
+
outDir: process.cwd(),
|
|
28117
|
+
...options.promptText !== void 0 ? { skillContentOverride: options.promptText } : {},
|
|
28118
|
+
...options.promptText === void 0 && options.promptPath ? { skillPathOverride: options.promptPath } : {}
|
|
28119
|
+
});
|
|
28120
|
+
const { result } = await invokeAgentWithOutput(
|
|
28121
|
+
invoker2,
|
|
28122
|
+
{ agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
|
|
28123
|
+
false
|
|
28124
|
+
);
|
|
28125
|
+
if (result.timedOut) throw new Error("selection agent timed out");
|
|
28126
|
+
if (result.exitCode !== 0) throw new Error(`selection agent exited with code ${result.exitCode}`);
|
|
28127
|
+
const parsed = parseSelectToolCallLines(result.stdout);
|
|
28128
|
+
for (const warning of parsed.warnings) process.stderr.write(`Warning: selection agent: ${warning}
|
|
27272
28129
|
`);
|
|
27273
|
-
|
|
28130
|
+
calls = parsed.calls;
|
|
28131
|
+
}
|
|
28132
|
+
const byName = new Map(calls.map((call) => [call.name, call]));
|
|
27274
28133
|
const writeDb = openPipelineDb();
|
|
27275
28134
|
try {
|
|
27276
28135
|
writeDb.exec("BEGIN");
|
|
@@ -27278,15 +28137,27 @@ async function runSelectionAgent(options) {
|
|
|
27278
28137
|
`UPDATE raw_components SET status = ?, reject_reason = ? WHERE session_id = ? AND component_id = ?`
|
|
27279
28138
|
);
|
|
27280
28139
|
for (const component of components) {
|
|
28140
|
+
const cached = cachedDecisions.get(component.name);
|
|
27281
28141
|
const call = byName.get(component.name);
|
|
27282
|
-
if (!call) continue;
|
|
27283
|
-
const rejected = call.tool === "reject_component";
|
|
28142
|
+
if (!cached && !call) continue;
|
|
28143
|
+
const rejected = cached ? cached.decision === "rejected" : call.tool === "reject_component";
|
|
28144
|
+
const reason = cached ? cached.reason : call.reason ?? null;
|
|
27284
28145
|
update.run(
|
|
27285
28146
|
rejected ? "rejected" : "accepted",
|
|
27286
|
-
rejected ?
|
|
28147
|
+
rejected ? reason : null,
|
|
27287
28148
|
options.sessionId,
|
|
27288
28149
|
component.component_id
|
|
27289
28150
|
);
|
|
28151
|
+
if (!cached) {
|
|
28152
|
+
storeSelectCache(
|
|
28153
|
+
writeDb,
|
|
28154
|
+
hashComponentShape(component),
|
|
28155
|
+
promptHash,
|
|
28156
|
+
cliVersion2,
|
|
28157
|
+
rejected ? "rejected" : "accepted",
|
|
28158
|
+
rejected ? reason : null
|
|
28159
|
+
);
|
|
28160
|
+
}
|
|
27290
28161
|
}
|
|
27291
28162
|
writeDb.exec("COMMIT");
|
|
27292
28163
|
} catch (error) {
|
|
@@ -27296,7 +28167,7 @@ async function runSelectionAgent(options) {
|
|
|
27296
28167
|
writeDb.close();
|
|
27297
28168
|
}
|
|
27298
28169
|
}
|
|
27299
|
-
var DEFAULT_TIMEOUT_MS4;
|
|
28170
|
+
var SELECT_PAYLOAD_FORMAT, DEFAULT_TIMEOUT_MS4;
|
|
27300
28171
|
var init_run_selection_agent = __esm({
|
|
27301
28172
|
"packages/experience-design-system-cli-legacy/src/import/tui/run-selection-agent.ts"() {
|
|
27302
28173
|
"use strict";
|
|
@@ -27307,6 +28178,8 @@ var init_run_selection_agent = __esm({
|
|
|
27307
28178
|
init_debug_logger();
|
|
27308
28179
|
init_agent_output();
|
|
27309
28180
|
init_db();
|
|
28181
|
+
init_cache_keys();
|
|
28182
|
+
SELECT_PAYLOAD_FORMAT = "prop-buckets-v1";
|
|
27310
28183
|
DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
|
|
27311
28184
|
}
|
|
27312
28185
|
});
|
|
@@ -27325,7 +28198,7 @@ __export(WizardApp_exports, {
|
|
|
27325
28198
|
});
|
|
27326
28199
|
import { useEffect as useEffect15, useRef as useRef10, useState as useState23 } from "react";
|
|
27327
28200
|
import { Box as Box42, Text as Text46 } from "ink";
|
|
27328
|
-
import { join as join23, resolve as
|
|
28201
|
+
import { join as join23, resolve as resolve18 } from "node:path";
|
|
27329
28202
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27330
28203
|
import { access as access7, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
27331
28204
|
import { tmpdir } from "node:os";
|
|
@@ -27338,21 +28211,28 @@ function buildGenerateComponentsArgs(opts) {
|
|
|
27338
28211
|
if (opts.tokensPath) args.push("--tokens", opts.tokensPath);
|
|
27339
28212
|
if (opts.model) args.push("--model", opts.model);
|
|
27340
28213
|
if (opts.bedrock) args.push("--bedrock");
|
|
28214
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27341
28215
|
if (opts.generatePromptPath) args.push("--generate-prompt-path", opts.generatePromptPath);
|
|
27342
28216
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27343
28217
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
28218
|
+
if (opts.restoreCache) args.push("--restore-cache");
|
|
28219
|
+
if (opts.cachedComponents && opts.cachedComponents.length > 0) {
|
|
28220
|
+
args.push("--cached-components", JSON.stringify(opts.cachedComponents));
|
|
28221
|
+
}
|
|
27344
28222
|
return args;
|
|
27345
28223
|
}
|
|
27346
28224
|
function buildGenerateTokensArgs(opts) {
|
|
27347
28225
|
const args = [findCliPath(), "__generate", "tokens", "--agent", opts.agent, "--raw-tokens", opts.rawTokensPath];
|
|
27348
28226
|
if (opts.model) args.push("--model", opts.model);
|
|
27349
28227
|
if (opts.bedrock) args.push("--bedrock");
|
|
28228
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27350
28229
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27351
28230
|
return args;
|
|
27352
28231
|
}
|
|
27353
28232
|
function buildMapTokensArgs(opts) {
|
|
27354
28233
|
const args = ["map", "tokens", "--session", opts.sessionId, "--agent", opts.agent];
|
|
27355
28234
|
if (opts.model) args.push("--model", opts.model);
|
|
28235
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27356
28236
|
if (opts.skipAgent) args.push("--skip-agent");
|
|
27357
28237
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27358
28238
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
@@ -27444,6 +28324,7 @@ function WizardApp({
|
|
|
27444
28324
|
initialProjectPath,
|
|
27445
28325
|
host,
|
|
27446
28326
|
promptOverrides,
|
|
28327
|
+
noCache = false,
|
|
27447
28328
|
livePreview = true,
|
|
27448
28329
|
generatePromptPath,
|
|
27449
28330
|
skipMapTokens = false,
|
|
@@ -27468,6 +28349,7 @@ function WizardApp({
|
|
|
27468
28349
|
});
|
|
27469
28350
|
const allowEmptyDeleteAllRef = useRef10(false);
|
|
27470
28351
|
const generateChildRef = useRef10(null);
|
|
28352
|
+
const generationCachePreflightRef = useRef10(null);
|
|
27471
28353
|
const selectionToReviewStartedAtRef = useRef10(null);
|
|
27472
28354
|
const credentialsValidationIdRef = useRef10(0);
|
|
27473
28355
|
const pendingCredentialValidationRef = useRef10(null);
|
|
@@ -27482,8 +28364,9 @@ function WizardApp({
|
|
|
27482
28364
|
const existingEntitiesPromiseRef = useRef10(null);
|
|
27483
28365
|
const generatePromiseRef = useRef10(null);
|
|
27484
28366
|
const rawTokensEntryReady = !!initialRawTokensPath;
|
|
28367
|
+
const effectiveNoCache = resolveNoCacheForGenerate({ cliNoCache: noCache });
|
|
27485
28368
|
const initialStepResolved = rawTokensEntryReady ? initialProjectPath ? "path-validation" : "credentials" : initialProjectPath ? "token-input" : "welcome";
|
|
27486
|
-
const initialOutDir = initialProjectPath ? join23(
|
|
28369
|
+
const initialOutDir = initialProjectPath ? join23(resolve18(initialProjectPath), ".contentful") : "";
|
|
27487
28370
|
const [state, setState] = useState23({
|
|
27488
28371
|
step: initialStepResolved,
|
|
27489
28372
|
agent: initialAgent ?? "claude",
|
|
@@ -27659,13 +28542,14 @@ If you are using AWS Bedrock, run:
|
|
|
27659
28542
|
if (!deferStep) update({ step: nextStep });
|
|
27660
28543
|
return true;
|
|
27661
28544
|
};
|
|
27662
|
-
const runGenerateTokens = async (rawTokensPath, outDir) => {
|
|
28545
|
+
const runGenerateTokens = async (rawTokensPath, outDir, forceRegenerate = false) => {
|
|
27663
28546
|
update({ tokenGenerationStatus: "running" });
|
|
27664
28547
|
const tokenArgs = buildGenerateTokensArgs({
|
|
27665
28548
|
rawTokensPath,
|
|
27666
28549
|
agent: state.agent,
|
|
27667
28550
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27668
28551
|
...state.bedrock ? { bedrock: true } : {},
|
|
28552
|
+
noCache: effectiveNoCache || forceRegenerate,
|
|
27669
28553
|
promptOverrides
|
|
27670
28554
|
});
|
|
27671
28555
|
const result = await runSpawnedCli(tokenArgs);
|
|
@@ -27714,6 +28598,7 @@ If you are using AWS Bedrock, run:
|
|
|
27714
28598
|
const timer = startWizardTimer("token-mapping", {
|
|
27715
28599
|
sessionId: sessionId2,
|
|
27716
28600
|
silent,
|
|
28601
|
+
noCache: effectiveNoCache,
|
|
27717
28602
|
skipAgent: skipMapTokens
|
|
27718
28603
|
});
|
|
27719
28604
|
let mappablePropCount = 0;
|
|
@@ -27722,7 +28607,7 @@ If you are using AWS Bedrock, run:
|
|
|
27722
28607
|
const db = openPipelineDb();
|
|
27723
28608
|
try {
|
|
27724
28609
|
if (state.tokenSessionId && state.tokenSessionId !== sessionId2) {
|
|
27725
|
-
|
|
28610
|
+
copyTokensFromCache(db, state.tokenSessionId, sessionId2);
|
|
27726
28611
|
} else if (!state.tokenSessionId && state.tokensPath) {
|
|
27727
28612
|
const tokens = await readTokensFromPath("tokens", state.tokensPath);
|
|
27728
28613
|
storeDtcgTokens(db, sessionId2, [], tokens);
|
|
@@ -27762,6 +28647,7 @@ If you are using AWS Bedrock, run:
|
|
|
27762
28647
|
sessionId: sessionId2,
|
|
27763
28648
|
agent: state.agent,
|
|
27764
28649
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28650
|
+
noCache: effectiveNoCache,
|
|
27765
28651
|
skipAgent: skipMapTokens,
|
|
27766
28652
|
promptOverrides,
|
|
27767
28653
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
|
|
@@ -27841,7 +28727,7 @@ If you are using AWS Bedrock, run:
|
|
|
27841
28727
|
return promise;
|
|
27842
28728
|
};
|
|
27843
28729
|
const runExtract = async (projectPath, showProgress = true) => {
|
|
27844
|
-
const outDir = join23(
|
|
28730
|
+
const outDir = join23(resolve18(projectPath), ".contentful");
|
|
27845
28731
|
const existingEntitiesExpected = !state.credentialsSkipped && Boolean(state.spaceId && state.environmentId && state.cmaToken && projectPath);
|
|
27846
28732
|
update({
|
|
27847
28733
|
...showProgress ? { step: "extracting" } : {},
|
|
@@ -27856,6 +28742,7 @@ If you are using AWS Bedrock, run:
|
|
|
27856
28742
|
});
|
|
27857
28743
|
const existingEntitiesPromise = startExistingEntitiesFetch(projectPath, outDir);
|
|
27858
28744
|
const extractArgs = [findCliPath(), "__extract", "--project", projectPath];
|
|
28745
|
+
if (effectiveNoCache) extractArgs.push("--no-cache");
|
|
27859
28746
|
let selectionPromptText;
|
|
27860
28747
|
let selectionPromptPath;
|
|
27861
28748
|
try {
|
|
@@ -27864,7 +28751,7 @@ If you are using AWS Bedrock, run:
|
|
|
27864
28751
|
const selectOverride = overrides.get("select");
|
|
27865
28752
|
if (selectOverride?.kind === "text") selectionPromptText = selectOverride.value;
|
|
27866
28753
|
if (selectOverride?.kind === "path") {
|
|
27867
|
-
selectionPromptPath =
|
|
28754
|
+
selectionPromptPath = resolve18(selectOverride.value);
|
|
27868
28755
|
await resolvePromptOverride(selectOverride);
|
|
27869
28756
|
}
|
|
27870
28757
|
} catch (error) {
|
|
@@ -27888,7 +28775,8 @@ If you are using AWS Bedrock, run:
|
|
|
27888
28775
|
agent: state.agent,
|
|
27889
28776
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27890
28777
|
...selectionPromptText !== void 0 ? { promptText: selectionPromptText } : {},
|
|
27891
|
-
...selectionPromptPath ? { promptPath: selectionPromptPath } : {}
|
|
28778
|
+
...selectionPromptPath ? { promptPath: selectionPromptPath } : {},
|
|
28779
|
+
noCache: effectiveNoCache
|
|
27892
28780
|
});
|
|
27893
28781
|
})().catch((error) => {
|
|
27894
28782
|
selectionError = error;
|
|
@@ -28033,17 +28921,136 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28033
28921
|
generateProgress: null
|
|
28034
28922
|
}));
|
|
28035
28923
|
};
|
|
28036
|
-
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2) => ({
|
|
28924
|
+
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => ({
|
|
28037
28925
|
sessionId: extractSessionId,
|
|
28038
28926
|
tokensPath,
|
|
28039
28927
|
agent: state.agent,
|
|
28040
28928
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28041
28929
|
...state.bedrock ? { bedrock: true } : {},
|
|
28930
|
+
noCache: effectiveNoCache,
|
|
28042
28931
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {},
|
|
28043
28932
|
...generatePromptPath2 ? { generatePromptPath: generatePromptPath2 } : {},
|
|
28044
|
-
promptOverrides
|
|
28933
|
+
promptOverrides,
|
|
28934
|
+
...cachedComponents && cachedComponents.length > 0 ? { cachedComponents } : {}
|
|
28045
28935
|
});
|
|
28046
|
-
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2));
|
|
28936
|
+
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents));
|
|
28937
|
+
const buildGenerateCliArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateComponentsArgs(
|
|
28938
|
+
buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents)
|
|
28939
|
+
);
|
|
28940
|
+
const checkGenerateCache = async (extractSessionId, tokensPath) => {
|
|
28941
|
+
const timer = startWizardTimer("generation-cache-status", {
|
|
28942
|
+
sessionId: extractSessionId,
|
|
28943
|
+
noCache: effectiveNoCache
|
|
28944
|
+
});
|
|
28945
|
+
if (effectiveNoCache) {
|
|
28946
|
+
finishWizardTimer("generation-cache-status", timer, { status: "skipped" });
|
|
28947
|
+
return false;
|
|
28948
|
+
}
|
|
28949
|
+
const result = await runCli([...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"]);
|
|
28950
|
+
const hit = result.exitCode === 0 && /^cache-status=hit$/m.test(result.stdout);
|
|
28951
|
+
finishWizardTimer("generation-cache-status", timer, {
|
|
28952
|
+
status: hit ? "hit" : "miss",
|
|
28953
|
+
exitCode: result.exitCode,
|
|
28954
|
+
...result.exitCode !== 0 ? { stderrTail: result.stderr.trim().slice(-500) } : {}
|
|
28955
|
+
});
|
|
28956
|
+
return hit;
|
|
28957
|
+
};
|
|
28958
|
+
const checkGenerateCacheComponents = async (extractSessionId, tokensPath, restoreCache = false) => {
|
|
28959
|
+
const timer = startWizardTimer("generation-cache-components", {
|
|
28960
|
+
sessionId: extractSessionId,
|
|
28961
|
+
restoreCache,
|
|
28962
|
+
noCache: effectiveNoCache
|
|
28963
|
+
});
|
|
28964
|
+
if (effectiveNoCache) {
|
|
28965
|
+
finishWizardTimer("generation-cache-components", timer, { status: "skipped" });
|
|
28966
|
+
return /* @__PURE__ */ new Set();
|
|
28967
|
+
}
|
|
28968
|
+
const args = [...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"];
|
|
28969
|
+
if (restoreCache) args.push("--restore-cache");
|
|
28970
|
+
const result = await runCli(args);
|
|
28971
|
+
if (result.exitCode !== 0) {
|
|
28972
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28973
|
+
status: "error",
|
|
28974
|
+
exitCode: result.exitCode,
|
|
28975
|
+
stderrTail: result.stderr.trim().slice(-500)
|
|
28976
|
+
});
|
|
28977
|
+
return /* @__PURE__ */ new Set();
|
|
28978
|
+
}
|
|
28979
|
+
const line = /^cache-components=(.+)$/m.exec(result.stdout)?.[1];
|
|
28980
|
+
if (!line) {
|
|
28981
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28982
|
+
status: "missing-output",
|
|
28983
|
+
exitCode: result.exitCode,
|
|
28984
|
+
cachedCount: 0
|
|
28985
|
+
});
|
|
28986
|
+
return /* @__PURE__ */ new Set();
|
|
28987
|
+
}
|
|
28988
|
+
try {
|
|
28989
|
+
const names = JSON.parse(line);
|
|
28990
|
+
const cachedNames = new Set(
|
|
28991
|
+
Array.isArray(names) ? names.filter((name) => typeof name === "string") : []
|
|
28992
|
+
);
|
|
28993
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28994
|
+
status: "complete",
|
|
28995
|
+
exitCode: result.exitCode,
|
|
28996
|
+
cachedCount: cachedNames.size
|
|
28997
|
+
});
|
|
28998
|
+
return cachedNames;
|
|
28999
|
+
} catch {
|
|
29000
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
29001
|
+
status: "invalid-output",
|
|
29002
|
+
exitCode: result.exitCode,
|
|
29003
|
+
cachedCount: 0
|
|
29004
|
+
});
|
|
29005
|
+
return /* @__PURE__ */ new Set();
|
|
29006
|
+
}
|
|
29007
|
+
};
|
|
29008
|
+
useEffect15(() => {
|
|
29009
|
+
if (state.step !== "extracting" && state.step !== "scope-gate" || !state.extractSessionId || state.existingEntitiesStatus === "running" || state.existingEntitiesStatus === "idle" || state.selectionAgentStatus !== "complete" || state.compositionPhase !== "done" || state.rawTokensPath && state.tokenGenerationStatus !== "complete" || effectiveNoCache) {
|
|
29010
|
+
return;
|
|
29011
|
+
}
|
|
29012
|
+
const sessionId2 = state.extractSessionId;
|
|
29013
|
+
if (generationCachePreflightRef.current?.sessionId === sessionId2) return;
|
|
29014
|
+
const timer = startWizardTimer("generation-cache-preflight", { sessionId: sessionId2 });
|
|
29015
|
+
const db = openPipelineDb();
|
|
29016
|
+
let generatedNames = null;
|
|
29017
|
+
try {
|
|
29018
|
+
const rows = db.prepare("SELECT name, status FROM raw_components WHERE session_id = ?").all(sessionId2);
|
|
29019
|
+
if (rows.length > 0 && rows.every((row) => row.status === "generated")) {
|
|
29020
|
+
generatedNames = new Set(rows.map((row) => row.name));
|
|
29021
|
+
}
|
|
29022
|
+
} finally {
|
|
29023
|
+
db.close();
|
|
29024
|
+
}
|
|
29025
|
+
if (generatedNames) {
|
|
29026
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: Promise.resolve(generatedNames) };
|
|
29027
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29028
|
+
status: "complete",
|
|
29029
|
+
source: "session-db",
|
|
29030
|
+
cachedCount: generatedNames.size
|
|
29031
|
+
});
|
|
29032
|
+
return;
|
|
29033
|
+
}
|
|
29034
|
+
const promise = checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
29035
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise };
|
|
29036
|
+
void promise.then((cachedNames) => {
|
|
29037
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29038
|
+
status: "complete",
|
|
29039
|
+
source: "cache-status",
|
|
29040
|
+
cachedCount: cachedNames.size
|
|
29041
|
+
});
|
|
29042
|
+
});
|
|
29043
|
+
}, [
|
|
29044
|
+
state.step,
|
|
29045
|
+
state.extractSessionId,
|
|
29046
|
+
state.tokensPath,
|
|
29047
|
+
state.rawTokensPath,
|
|
29048
|
+
state.tokenGenerationStatus,
|
|
29049
|
+
state.selectionAgentStatus,
|
|
29050
|
+
state.compositionPhase,
|
|
29051
|
+
state.existingEntitiesStatus,
|
|
29052
|
+
state.existingEntitiesPath
|
|
29053
|
+
]);
|
|
28047
29054
|
const startGeneratePrefetch = (extractSessionId, tokensPath) => {
|
|
28048
29055
|
const args = buildGenerateArgs(extractSessionId, tokensPath);
|
|
28049
29056
|
let progressCursor = null;
|
|
@@ -28098,13 +29105,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28098
29105
|
});
|
|
28099
29106
|
return donePromise;
|
|
28100
29107
|
};
|
|
28101
|
-
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false) => {
|
|
29108
|
+
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false, cachedComponents = []) => {
|
|
28102
29109
|
const timer = startWizardTimer("component-generation", {
|
|
28103
29110
|
sessionId: extractSessionId,
|
|
28104
29111
|
acceptedCount,
|
|
28105
|
-
suppressScreen
|
|
29112
|
+
suppressScreen,
|
|
29113
|
+
noCache: effectiveNoCache
|
|
28106
29114
|
});
|
|
28107
|
-
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath);
|
|
29115
|
+
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath, cachedComponents);
|
|
28108
29116
|
let progressCursor = state.generateProgress;
|
|
28109
29117
|
const { donePromise } = spawnGenerateChild({
|
|
28110
29118
|
command: "node",
|
|
@@ -28174,6 +29182,25 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28174
29182
|
finishSelectionToReviewTimer("error");
|
|
28175
29183
|
}
|
|
28176
29184
|
};
|
|
29185
|
+
const finishCachedGeneration = async (sessionId2, acceptedCount) => {
|
|
29186
|
+
if (await runMapTokens2(sessionId2, true)) {
|
|
29187
|
+
finishSelectionToReviewTimer("cached");
|
|
29188
|
+
update(
|
|
29189
|
+
{
|
|
29190
|
+
acceptedCount,
|
|
29191
|
+
autoRejectedCount: 0,
|
|
29192
|
+
generateSessionId: sessionId2,
|
|
29193
|
+
generatedCount: acceptedCount,
|
|
29194
|
+
generateProgress: null,
|
|
29195
|
+
mapTokensStatus: "complete",
|
|
29196
|
+
step: "final-review"
|
|
29197
|
+
},
|
|
29198
|
+
{ clearScreen: false }
|
|
29199
|
+
);
|
|
29200
|
+
} else {
|
|
29201
|
+
finishSelectionToReviewTimer("error");
|
|
29202
|
+
}
|
|
29203
|
+
};
|
|
28177
29204
|
const advanceToPushFlow = (generatedAcceptedCount) => {
|
|
28178
29205
|
update({ generatedAcceptedCount });
|
|
28179
29206
|
void runSaveAndPush();
|
|
@@ -28358,8 +29385,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28358
29385
|
}
|
|
28359
29386
|
}
|
|
28360
29387
|
if (await runAgentAuthCheck("generating", true)) {
|
|
28361
|
-
|
|
28362
|
-
|
|
29388
|
+
const cacheHit = await checkGenerateCache(sid, state.tokensPath);
|
|
29389
|
+
if (cacheHit) {
|
|
29390
|
+
update({ step: "generating" });
|
|
29391
|
+
void finishCachedGeneration(sid, state.acceptedCount);
|
|
29392
|
+
} else {
|
|
29393
|
+
update({ step: "generating" });
|
|
29394
|
+
void runGenerate(sid, state.tokensPath, state.acceptedCount);
|
|
29395
|
+
}
|
|
28363
29396
|
}
|
|
28364
29397
|
return;
|
|
28365
29398
|
}
|
|
@@ -28723,7 +29756,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28723
29756
|
});
|
|
28724
29757
|
return { ok: false };
|
|
28725
29758
|
}
|
|
28726
|
-
await new Promise((
|
|
29759
|
+
await new Promise((resolve21) => setTimeout(resolve21, SAVE_CONFIRMATION_DELAY_MS));
|
|
28727
29760
|
update(nextStateAfterPrint({ skipGate: opts.skipGate, componentsPath }));
|
|
28728
29761
|
return { ok: true };
|
|
28729
29762
|
};
|
|
@@ -28800,6 +29833,12 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28800
29833
|
tokenReuseChecked.current = true;
|
|
28801
29834
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28802
29835
|
const existingTokensPath = join23(state.outDir, "tokens.json");
|
|
29836
|
+
if (effectiveNoCache) {
|
|
29837
|
+
tokenGenerationPromiseRef.current = runAgentAuthCheck(tokenNextStep).then(
|
|
29838
|
+
(ok2) => ok2 ? runGenerateTokens(state.rawTokensPath, state.outDir) : false
|
|
29839
|
+
);
|
|
29840
|
+
return;
|
|
29841
|
+
}
|
|
28803
29842
|
(async () => {
|
|
28804
29843
|
try {
|
|
28805
29844
|
await access7(existingTokensPath);
|
|
@@ -28883,7 +29922,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28883
29922
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28884
29923
|
update({ step: tokenNextStep });
|
|
28885
29924
|
if (await runAgentAuthCheck(tokenNextStep)) {
|
|
28886
|
-
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir);
|
|
29925
|
+
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir, true);
|
|
28887
29926
|
}
|
|
28888
29927
|
},
|
|
28889
29928
|
onQuit: () => process.exit(0)
|
|
@@ -28982,6 +30021,29 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28982
30021
|
acceptedCount: decisions.accepted.length,
|
|
28983
30022
|
rejectedCount: decisions.rejected.length
|
|
28984
30023
|
}) : null;
|
|
30024
|
+
const preflight = generationCachePreflightRef.current;
|
|
30025
|
+
const cachePromise = preflight?.sessionId === sessionId2 ? preflight.promise : checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
30026
|
+
if (!preflight || preflight.sessionId !== sessionId2) {
|
|
30027
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: cachePromise };
|
|
30028
|
+
}
|
|
30029
|
+
const cacheWaitStartedAt = startWizardTimer("selection-cache-restoration-wait", {
|
|
30030
|
+
sessionId: sessionId2,
|
|
30031
|
+
preflight: Boolean(preflight?.sessionId === sessionId2)
|
|
30032
|
+
});
|
|
30033
|
+
try {
|
|
30034
|
+
const cachedNames = await cachePromise;
|
|
30035
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30036
|
+
status: "complete",
|
|
30037
|
+
cachedCount: cachedNames.size
|
|
30038
|
+
});
|
|
30039
|
+
} catch (error) {
|
|
30040
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30041
|
+
status: "error",
|
|
30042
|
+
error: error instanceof Error ? error.message : String(error)
|
|
30043
|
+
});
|
|
30044
|
+
finishSelectionToReviewTimer("error");
|
|
30045
|
+
throw error;
|
|
30046
|
+
}
|
|
28985
30047
|
await runScopeGate({
|
|
28986
30048
|
sessionId: sessionId2,
|
|
28987
30049
|
decisions,
|
|
@@ -28990,12 +30052,35 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28990
30052
|
if (shouldGenerateAfterScopeGate({ acceptedCount })) {
|
|
28991
30053
|
const authPromise = runAgentAuthCheck("generating", true);
|
|
28992
30054
|
if (await authPromise) {
|
|
28993
|
-
|
|
28994
|
-
|
|
28995
|
-
|
|
28996
|
-
acceptedCount
|
|
30055
|
+
const comparisonStartedAt = startWizardTimer("generation-cache-set-comparison", {
|
|
30056
|
+
sessionId: sid,
|
|
30057
|
+
acceptedCount: decisions?.accepted.length ?? 0
|
|
28997
30058
|
});
|
|
28998
|
-
|
|
30059
|
+
let cachedNames = await cachePromise;
|
|
30060
|
+
const acceptedNames = decisions?.accepted ?? [];
|
|
30061
|
+
let cacheHit = !effectiveNoCache && acceptedNames.length > 0 && acceptedNames.every((name) => cachedNames.has(name));
|
|
30062
|
+
if (!cacheHit && !effectiveNoCache && acceptedNames.length > 0) {
|
|
30063
|
+
cachedNames = await checkGenerateCacheComponents(sid, state.tokensPath, true);
|
|
30064
|
+
cacheHit = acceptedNames.every((name) => cachedNames.has(name));
|
|
30065
|
+
}
|
|
30066
|
+
finishWizardTimer("generation-cache-set-comparison", comparisonStartedAt, {
|
|
30067
|
+
status: "complete",
|
|
30068
|
+
cacheHit,
|
|
30069
|
+
cachedCount: cachedNames.size,
|
|
30070
|
+
acceptedCount: acceptedNames.length
|
|
30071
|
+
});
|
|
30072
|
+
if (cacheHit) {
|
|
30073
|
+
void finishCachedGeneration(sid, acceptedCount);
|
|
30074
|
+
} else {
|
|
30075
|
+
const acceptedNameSet = new Set(acceptedNames);
|
|
30076
|
+
const restoredCachedNames = [...cachedNames].filter((name) => acceptedNameSet.has(name));
|
|
30077
|
+
update({
|
|
30078
|
+
step: "generating",
|
|
30079
|
+
generateProgress: null,
|
|
30080
|
+
acceptedCount
|
|
30081
|
+
});
|
|
30082
|
+
void runGenerate(sid, state.tokensPath, acceptedCount, false, restoredCachedNames);
|
|
30083
|
+
}
|
|
28999
30084
|
} else {
|
|
29000
30085
|
finishSelectionToReviewTimer("error");
|
|
29001
30086
|
}
|
|
@@ -29361,7 +30446,7 @@ function registerImportCommand(program) {
|
|
|
29361
30446
|
"Override a composition, selection, token, generation, or token-mapping prompt (repeatable). value is a file path or literal text, e.g. --prompt select=./p.md",
|
|
29362
30447
|
(v, acc) => [...acc, v],
|
|
29363
30448
|
[]
|
|
29364
|
-
).action(async (opts) => {
|
|
30449
|
+
).option("--no-cache", "Re-run all steps even if output already exists").action(async (opts) => {
|
|
29365
30450
|
const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
|
|
29366
30451
|
if (opts.tokens !== void 0) {
|
|
29367
30452
|
const { access: access9 } = await import("node:fs/promises");
|
|
@@ -29398,6 +30483,7 @@ function registerImportCommand(program) {
|
|
|
29398
30483
|
...resolvedModel ? { initialModel: resolvedModel } : {},
|
|
29399
30484
|
initialProjectPath: opts.project !== "." ? normalizePath(opts.project) : void 0,
|
|
29400
30485
|
...buildCompositionForwardingOptions(opts),
|
|
30486
|
+
noCache: opts.cache === false,
|
|
29401
30487
|
skipMapTokens: false,
|
|
29402
30488
|
livePreview: true,
|
|
29403
30489
|
generatePromptPath: creds.generatePromptPath,
|
|
@@ -29485,7 +30571,7 @@ async function pathExists3(path) {
|
|
|
29485
30571
|
return access8(path).then(() => true).catch(() => false);
|
|
29486
30572
|
}
|
|
29487
30573
|
function runSpawn(cmd, args, opts = {}) {
|
|
29488
|
-
return new Promise((
|
|
30574
|
+
return new Promise((resolve21) => {
|
|
29489
30575
|
const child = spawn6(cmd, args, {
|
|
29490
30576
|
cwd: opts.cwd,
|
|
29491
30577
|
env: opts.env ?? process.env,
|
|
@@ -29497,7 +30583,7 @@ function runSpawn(cmd, args, opts = {}) {
|
|
|
29497
30583
|
const settle = (result) => {
|
|
29498
30584
|
if (settled) return;
|
|
29499
30585
|
settled = true;
|
|
29500
|
-
|
|
30586
|
+
resolve21(result);
|
|
29501
30587
|
};
|
|
29502
30588
|
child.on("error", (err) => settle({ exitCode: 1, stdout: "", stderr: err.message }));
|
|
29503
30589
|
child.stdout.on("data", (d) => {
|
|
@@ -30698,13 +31784,13 @@ function PrerequisitesScreen({
|
|
|
30698
31784
|
const driver = {
|
|
30699
31785
|
...base,
|
|
30700
31786
|
emit: (event) => setEvents((current) => [...current, event]),
|
|
30701
|
-
confirm: (question, defaultYes = true) => new Promise((
|
|
31787
|
+
confirm: (question, defaultYes = true) => new Promise((resolve21) => {
|
|
30702
31788
|
setConfirm({
|
|
30703
31789
|
question,
|
|
30704
31790
|
defaultYes,
|
|
30705
31791
|
resolve: (answer) => {
|
|
30706
31792
|
setConfirm(null);
|
|
30707
|
-
|
|
31793
|
+
resolve21(answer);
|
|
30708
31794
|
}
|
|
30709
31795
|
});
|
|
30710
31796
|
})
|
|
@@ -30779,8 +31865,8 @@ function SetupScreen({
|
|
|
30779
31865
|
useEffect21(() => {
|
|
30780
31866
|
if (startedRef.current) return;
|
|
30781
31867
|
startedRef.current = true;
|
|
30782
|
-
const runScreen = (build) => new Promise((
|
|
30783
|
-
setScreen(build(
|
|
31868
|
+
const runScreen = (build) => new Promise((resolve21) => {
|
|
31869
|
+
setScreen(build(resolve21));
|
|
30784
31870
|
});
|
|
30785
31871
|
void (async () => {
|
|
30786
31872
|
const results = [];
|
|
@@ -31388,8 +32474,11 @@ var init_source_call_site_evidence = __esm({
|
|
|
31388
32474
|
});
|
|
31389
32475
|
|
|
31390
32476
|
// packages/experience-design-system-cli-legacy/src/analyze/extract-command.ts
|
|
31391
|
-
import { mkdir as mkdir6, readdir as readdir3, readFile as
|
|
31392
|
-
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as
|
|
32477
|
+
import { mkdir as mkdir6, readdir as readdir3, readFile as readFile19, stat as stat6 } from "node:fs/promises";
|
|
32478
|
+
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as resolve19 } from "node:path";
|
|
32479
|
+
function resolveExtractNoCache(opts) {
|
|
32480
|
+
return opts.noCache === true || opts.cache === false;
|
|
32481
|
+
}
|
|
31393
32482
|
function isDenylistedNoiseFile(name) {
|
|
31394
32483
|
return DENYLISTED_EXACT_FILE_NAMES.has(name) || DENYLISTED_FILE_NAME_PATTERNS.some((pattern) => pattern.test(name));
|
|
31395
32484
|
}
|
|
@@ -31403,12 +32492,12 @@ async function retryDatabaseWrite(operation, attempts = 8) {
|
|
|
31403
32492
|
} catch (error) {
|
|
31404
32493
|
const message = error instanceof Error ? error.message : String(error);
|
|
31405
32494
|
if (!/database is locked|database is busy/i.test(message) || attempt >= attempts) throw error;
|
|
31406
|
-
await new Promise((
|
|
32495
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(250 * attempt, 2e3)));
|
|
31407
32496
|
}
|
|
31408
32497
|
}
|
|
31409
32498
|
}
|
|
31410
32499
|
function resolveFromProjectRoot(projectRoot, inputPath) {
|
|
31411
|
-
return isAbsolute2(inputPath) ? inputPath :
|
|
32500
|
+
return isAbsolute2(inputPath) ? inputPath : resolve19(projectRoot, inputPath);
|
|
31412
32501
|
}
|
|
31413
32502
|
async function pathExists4(path) {
|
|
31414
32503
|
return Boolean(await stat6(path).catch(() => null));
|
|
@@ -31455,7 +32544,7 @@ async function readCandidateFiles(components, extraFiles = []) {
|
|
|
31455
32544
|
await Promise.all(
|
|
31456
32545
|
[...paths].map(async (p) => {
|
|
31457
32546
|
try {
|
|
31458
|
-
const content = await
|
|
32547
|
+
const content = await readFile19(p, "utf8");
|
|
31459
32548
|
out.push({ path: p, content });
|
|
31460
32549
|
} catch {
|
|
31461
32550
|
}
|
|
@@ -31468,7 +32557,8 @@ function registerInternalExtractCommand(program) {
|
|
|
31468
32557
|
"--resolve-unreachable <mode>",
|
|
31469
32558
|
"Retry pass for unresolved Svelte Props types: 'auto' (default), 'always', or 'never'",
|
|
31470
32559
|
"auto"
|
|
31471
|
-
).action(async (opts) => {
|
|
32560
|
+
).option("--no-cache", "Re-run extraction even when all source files are unchanged").action(async (opts) => {
|
|
32561
|
+
const noCache = resolveExtractNoCache(opts);
|
|
31472
32562
|
const resolveUnreachable = (() => {
|
|
31473
32563
|
const v = opts.resolveUnreachable ?? "auto";
|
|
31474
32564
|
if (v !== "auto" && v !== "always" && v !== "never") {
|
|
@@ -31478,7 +32568,7 @@ function registerInternalExtractCommand(program) {
|
|
|
31478
32568
|
}
|
|
31479
32569
|
return v;
|
|
31480
32570
|
})();
|
|
31481
|
-
const projectRoot =
|
|
32571
|
+
const projectRoot = resolve19(opts.project);
|
|
31482
32572
|
const outDir = join27(projectRoot, ".contentful");
|
|
31483
32573
|
let sourceDirectory;
|
|
31484
32574
|
if (opts.dir !== void 0) {
|
|
@@ -31502,16 +32592,50 @@ function registerInternalExtractCommand(program) {
|
|
|
31502
32592
|
process.stderr.write(`progress=scan-done:${sourceFiles.length}
|
|
31503
32593
|
`);
|
|
31504
32594
|
}
|
|
31505
|
-
const
|
|
31506
|
-
|
|
31507
|
-
|
|
32595
|
+
const extractionCacheDb = openPipelineDb();
|
|
32596
|
+
let extraction;
|
|
32597
|
+
let extractionCacheHits = 0;
|
|
32598
|
+
try {
|
|
32599
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32600
|
+
const cachedByPath = /* @__PURE__ */ new Map();
|
|
32601
|
+
if (!noCache && sourceFiles.length > 0) {
|
|
32602
|
+
const hashes = await Promise.all(
|
|
32603
|
+
sourceFiles.map(async (filePath) => [filePath, await hashFile(filePath)])
|
|
32604
|
+
);
|
|
32605
|
+
for (const [filePath, fileHash] of hashes) {
|
|
32606
|
+
cachedByPath.set(filePath, lookupExtractCache(extractionCacheDb, fileHash, cacheVersion));
|
|
32607
|
+
}
|
|
32608
|
+
}
|
|
32609
|
+
const allFilesCached = !noCache && sourceFiles.length > 0 && sourceFiles.every((filePath) => cachedByPath.get(filePath) !== null);
|
|
32610
|
+
if (allFilesCached) {
|
|
32611
|
+
const cachedComponents = sourceFiles.flatMap((filePath) => cachedByPath.get(filePath).components);
|
|
32612
|
+
extractionCacheHits = sourceFiles.length;
|
|
32613
|
+
extraction = { components: cachedComponents, warnings: [], exclusions: [] };
|
|
31508
32614
|
if (!process.stdout.isTTY) {
|
|
31509
|
-
process.stderr.write(
|
|
31510
|
-
`
|
|
32615
|
+
process.stderr.write(
|
|
32616
|
+
`progress=extract:${sourceFiles.length}/${sourceFiles.length}:${cachedComponents.length}
|
|
32617
|
+
`
|
|
32618
|
+
);
|
|
31511
32619
|
}
|
|
31512
|
-
|
|
31513
|
-
|
|
31514
|
-
|
|
32620
|
+
getDebugLogger().event("analyze", "extract.cache-hit", {
|
|
32621
|
+
files: sourceFiles.length,
|
|
32622
|
+
components: cachedComponents.length
|
|
32623
|
+
});
|
|
32624
|
+
} else {
|
|
32625
|
+
extraction = await extractComponents(
|
|
32626
|
+
sourceFiles,
|
|
32627
|
+
({ filesProcessed, componentsFound }) => {
|
|
32628
|
+
if (!process.stdout.isTTY) {
|
|
32629
|
+
process.stderr.write(`progress=extract:${filesProcessed}/${sourceFiles.length}:${componentsFound}
|
|
32630
|
+
`);
|
|
32631
|
+
}
|
|
32632
|
+
},
|
|
32633
|
+
{ resolveUnreachable, projectRoot }
|
|
32634
|
+
);
|
|
32635
|
+
}
|
|
32636
|
+
} finally {
|
|
32637
|
+
extractionCacheDb.close();
|
|
32638
|
+
}
|
|
31515
32639
|
await mkdir6(outDir, { recursive: true });
|
|
31516
32640
|
const db = openPipelineDb();
|
|
31517
32641
|
const { sessionId: sessionId2 } = getOrCreateSession(db, void 0, void 0, {
|
|
@@ -31526,6 +32650,25 @@ function registerInternalExtractCommand(program) {
|
|
|
31526
32650
|
const stepId = createStep(db, sessionId2, "analyze extract", {
|
|
31527
32651
|
project: projectRoot
|
|
31528
32652
|
});
|
|
32653
|
+
if (extractionCacheHits === 0 && !noCache) {
|
|
32654
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32655
|
+
const componentsBySourcePath = /* @__PURE__ */ new Map();
|
|
32656
|
+
for (const component of extraction.components) {
|
|
32657
|
+
if (!component.sourcePath) continue;
|
|
32658
|
+
const components = componentsBySourcePath.get(component.sourcePath) ?? [];
|
|
32659
|
+
components.push(component);
|
|
32660
|
+
componentsBySourcePath.set(component.sourcePath, components);
|
|
32661
|
+
}
|
|
32662
|
+
for (const filePath of sourceFiles) {
|
|
32663
|
+
storeExtractCache(
|
|
32664
|
+
db,
|
|
32665
|
+
filePath,
|
|
32666
|
+
await hashFile(filePath),
|
|
32667
|
+
cacheVersion,
|
|
32668
|
+
componentsBySourcePath.get(filePath) ?? []
|
|
32669
|
+
);
|
|
32670
|
+
}
|
|
32671
|
+
}
|
|
31529
32672
|
const classifiedComponents = extraction.components.map(preClassifyComponent);
|
|
31530
32673
|
for (const exclusion of extraction.exclusions ?? []) {
|
|
31531
32674
|
getDebugLogger().event("filter", "extract.excluded", { ...exclusion });
|
|
@@ -31630,6 +32773,7 @@ var init_extract_command = __esm({
|
|
|
31630
32773
|
"use strict";
|
|
31631
32774
|
init_src2();
|
|
31632
32775
|
init_db();
|
|
32776
|
+
init_cache_keys();
|
|
31633
32777
|
init_cycle_detection();
|
|
31634
32778
|
init_resolve_mapping();
|
|
31635
32779
|
init_manifest_doc_evidence();
|
|
@@ -31728,7 +32872,7 @@ __export(program_exports, {
|
|
|
31728
32872
|
});
|
|
31729
32873
|
import { spawn as spawn7 } from "node:child_process";
|
|
31730
32874
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
31731
|
-
import { dirname as dirname18, join as join28, resolve as
|
|
32875
|
+
import { dirname as dirname18, join as join28, resolve as resolve20 } from "node:path";
|
|
31732
32876
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
31733
32877
|
import { Command } from "commander";
|
|
31734
32878
|
async function runBuild(opts) {
|
|
@@ -31758,7 +32902,7 @@ function resolveBedrockFromAncestors(actionCommand) {
|
|
|
31758
32902
|
}
|
|
31759
32903
|
function registerBuildCommand(program) {
|
|
31760
32904
|
program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").helpOption(false).action(async () => {
|
|
31761
|
-
const pkgRoot =
|
|
32905
|
+
const pkgRoot = resolve20(dirname18(fileURLToPath3(import.meta.url)), "..", "..");
|
|
31762
32906
|
process.stderr.write("\u2699 Building from source...\n");
|
|
31763
32907
|
const { exitCode } = await runBuild({
|
|
31764
32908
|
spawnFn: () => spawn7("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|