@contentful/experience-design-system-cli 2.35.1-dev-build-98f1ba74.0 → 2.35.1-dev-build-c8bff53c.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 +1328 -184
- 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";
|
|
@@ -10272,6 +10357,41 @@ var init_read3 = __esm({
|
|
|
10272
10357
|
}
|
|
10273
10358
|
});
|
|
10274
10359
|
|
|
10360
|
+
// packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts
|
|
10361
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
10362
|
+
function hashComponentShape(component) {
|
|
10363
|
+
const payload = {
|
|
10364
|
+
framework: component.framework,
|
|
10365
|
+
name: component.name,
|
|
10366
|
+
source: component.source,
|
|
10367
|
+
props: component.props.map((p) => ({
|
|
10368
|
+
name: p.name,
|
|
10369
|
+
type: p.type
|
|
10370
|
+
})),
|
|
10371
|
+
slots: component.slots.map((s) => ({
|
|
10372
|
+
name: s.name,
|
|
10373
|
+
isDefault: s.isDefault
|
|
10374
|
+
}))
|
|
10375
|
+
};
|
|
10376
|
+
return createHash2("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
10377
|
+
}
|
|
10378
|
+
var init_hash_component_shape = __esm({
|
|
10379
|
+
"packages/experience-design-system-cli-legacy/src/session/core/components/hash-component-shape.ts"() {
|
|
10380
|
+
"use strict";
|
|
10381
|
+
}
|
|
10382
|
+
});
|
|
10383
|
+
|
|
10384
|
+
// packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts
|
|
10385
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
10386
|
+
function hashTokenContent(rawTokenContent) {
|
|
10387
|
+
return createHash3("sha256").update(rawTokenContent.trim()).digest("hex");
|
|
10388
|
+
}
|
|
10389
|
+
var init_hash_token_content = __esm({
|
|
10390
|
+
"packages/experience-design-system-cli-legacy/src/session/core/tokens/hash-token-content.ts"() {
|
|
10391
|
+
"use strict";
|
|
10392
|
+
}
|
|
10393
|
+
});
|
|
10394
|
+
|
|
10275
10395
|
// packages/experience-design-system-cli-legacy/src/session/repositories/tokens/write.ts
|
|
10276
10396
|
function deleteRawTokensForSession(db, sessionId2) {
|
|
10277
10397
|
db.prepare("DELETE FROM raw_token_groups WHERE session_id = ?").run(sessionId2);
|
|
@@ -10435,17 +10555,47 @@ var init_replace_raw_prop_token_paths = __esm({
|
|
|
10435
10555
|
}
|
|
10436
10556
|
});
|
|
10437
10557
|
|
|
10558
|
+
// packages/experience-design-system-cli-legacy/src/session/cache-keys.ts
|
|
10559
|
+
var cache_keys_exports = {};
|
|
10560
|
+
__export(cache_keys_exports, {
|
|
10561
|
+
hashContent: () => hashContent,
|
|
10562
|
+
hashFile: () => hashFile,
|
|
10563
|
+
hashPromptForSkill: () => hashPromptForSkill
|
|
10564
|
+
});
|
|
10565
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
10566
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
10567
|
+
import { resolve as resolve8 } from "node:path";
|
|
10568
|
+
function hashContent(content) {
|
|
10569
|
+
return createHash4("sha256").update(content).digest("hex");
|
|
10570
|
+
}
|
|
10571
|
+
async function hashFile(filePath) {
|
|
10572
|
+
const content = await readFile7(filePath, "utf8");
|
|
10573
|
+
return hashContent(content);
|
|
10574
|
+
}
|
|
10575
|
+
async function hashPromptForSkill(skill, agent, model, skillPathOverride, extraInputs = [], skillContentOverride) {
|
|
10576
|
+
const promptHash = skillContentOverride ? hashContent(skillContentOverride) : skillPathOverride ? await hashFile(resolve8(skillPathOverride)) : await hashFile(resolveSkillPath(skill));
|
|
10577
|
+
const extraSegment = extraInputs.length > 0 ? `|${extraInputs.join("|")}` : "";
|
|
10578
|
+
return hashContent(`${promptHash}|${agent}|${model ?? ""}${extraSegment}`);
|
|
10579
|
+
}
|
|
10580
|
+
var init_cache_keys = __esm({
|
|
10581
|
+
"packages/experience-design-system-cli-legacy/src/session/cache-keys.ts"() {
|
|
10582
|
+
"use strict";
|
|
10583
|
+
init_src();
|
|
10584
|
+
}
|
|
10585
|
+
});
|
|
10586
|
+
|
|
10438
10587
|
// packages/experience-design-system-cli-legacy/src/session/db.ts
|
|
10439
10588
|
import { DatabaseSync } from "node:sqlite";
|
|
10440
10589
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
10441
|
-
import { readFile as
|
|
10590
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
10591
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
10442
10592
|
import { homedir as homedir3 } from "node:os";
|
|
10443
|
-
import { dirname as dirname14, resolve as
|
|
10593
|
+
import { dirname as dirname14, resolve as resolve9 } from "node:path";
|
|
10444
10594
|
function getPipelineDbPath() {
|
|
10445
10595
|
if (process.env.EDS_PIPELINE_DB_PATH) {
|
|
10446
|
-
return
|
|
10596
|
+
return resolve9(process.env.EDS_PIPELINE_DB_PATH);
|
|
10447
10597
|
}
|
|
10448
|
-
return
|
|
10598
|
+
return resolve9(homedir3(), ".contentful", "experience-design-system-cli", "pipeline.db");
|
|
10449
10599
|
}
|
|
10450
10600
|
function openPipelineDb(dbPath) {
|
|
10451
10601
|
const path = dbPath ?? getPipelineDbPath();
|
|
@@ -10579,8 +10729,134 @@ function applyDbMigrations(db) {
|
|
|
10579
10729
|
if (!rawSlotColsForRationale.some((c2) => c2.name === "rationale")) {
|
|
10580
10730
|
db.exec("ALTER TABLE raw_slots ADD COLUMN rationale TEXT");
|
|
10581
10731
|
}
|
|
10582
|
-
|
|
10583
|
-
|
|
10732
|
+
const hasExtractCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='extract_cache'`).all();
|
|
10733
|
+
if (hasExtractCache.length === 0) {
|
|
10734
|
+
db.exec(`
|
|
10735
|
+
CREATE TABLE extract_cache (
|
|
10736
|
+
file_path TEXT NOT NULL,
|
|
10737
|
+
file_hash TEXT NOT NULL,
|
|
10738
|
+
cli_version TEXT NOT NULL,
|
|
10739
|
+
created_at TEXT NOT NULL,
|
|
10740
|
+
updated_at TEXT NOT NULL,
|
|
10741
|
+
components_json TEXT NOT NULL,
|
|
10742
|
+
PRIMARY KEY (file_hash, cli_version)
|
|
10743
|
+
);
|
|
10744
|
+
CREATE INDEX idx_extract_cache_file ON extract_cache(file_path);
|
|
10745
|
+
`);
|
|
10746
|
+
}
|
|
10747
|
+
const hasSelectCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='select_cache'`).all();
|
|
10748
|
+
if (hasSelectCache.length === 0) {
|
|
10749
|
+
db.exec(`
|
|
10750
|
+
CREATE TABLE select_cache (
|
|
10751
|
+
component_hash TEXT NOT NULL,
|
|
10752
|
+
prompt_hash TEXT NOT NULL,
|
|
10753
|
+
cli_version TEXT NOT NULL,
|
|
10754
|
+
decision TEXT NOT NULL CHECK (decision IN ('accepted','rejected')),
|
|
10755
|
+
reason TEXT,
|
|
10756
|
+
created_at TEXT NOT NULL,
|
|
10757
|
+
updated_at TEXT NOT NULL,
|
|
10758
|
+
PRIMARY KEY (component_hash, prompt_hash, cli_version)
|
|
10759
|
+
);
|
|
10760
|
+
`);
|
|
10761
|
+
}
|
|
10762
|
+
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='generation_cache'`).all();
|
|
10763
|
+
if (tables.length === 0) {
|
|
10764
|
+
db.exec(`
|
|
10765
|
+
CREATE TABLE generation_cache (
|
|
10766
|
+
input_hash TEXT NOT NULL,
|
|
10767
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10768
|
+
entity_id TEXT NOT NULL,
|
|
10769
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10770
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10771
|
+
created_at TEXT NOT NULL,
|
|
10772
|
+
updated_at TEXT NOT NULL,
|
|
10773
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
10774
|
+
);
|
|
10775
|
+
CREATE INDEX idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10776
|
+
CREATE INDEX idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10777
|
+
`);
|
|
10778
|
+
}
|
|
10779
|
+
const genCacheCols = db.prepare(`PRAGMA table_info(generation_cache)`).all();
|
|
10780
|
+
const hasPromptHash = genCacheCols.some((c2) => c2.name === "prompt_hash");
|
|
10781
|
+
const oldPkCols = genCacheCols.filter((c2) => c2.pk > 0).map((c2) => c2.name);
|
|
10782
|
+
const promptHashInPk = oldPkCols.includes("prompt_hash");
|
|
10783
|
+
if (!hasPromptHash) {
|
|
10784
|
+
db.exec(`ALTER TABLE generation_cache ADD COLUMN prompt_hash TEXT NOT NULL DEFAULT ''`);
|
|
10785
|
+
}
|
|
10786
|
+
if (!promptHashInPk) {
|
|
10787
|
+
db.exec("BEGIN");
|
|
10788
|
+
try {
|
|
10789
|
+
db.exec(`
|
|
10790
|
+
CREATE TABLE generation_cache__new (
|
|
10791
|
+
input_hash TEXT NOT NULL,
|
|
10792
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10793
|
+
entity_id TEXT NOT NULL,
|
|
10794
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10795
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10796
|
+
created_at TEXT NOT NULL,
|
|
10797
|
+
updated_at TEXT NOT NULL,
|
|
10798
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10799
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10800
|
+
);
|
|
10801
|
+
INSERT INTO generation_cache__new
|
|
10802
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10803
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10804
|
+
FROM generation_cache;
|
|
10805
|
+
DROP TABLE generation_cache;
|
|
10806
|
+
ALTER TABLE generation_cache__new RENAME TO generation_cache;
|
|
10807
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10808
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10809
|
+
`);
|
|
10810
|
+
db.exec("COMMIT");
|
|
10811
|
+
} catch (e) {
|
|
10812
|
+
db.exec("ROLLBACK");
|
|
10813
|
+
throw e;
|
|
10814
|
+
}
|
|
10815
|
+
}
|
|
10816
|
+
const genCacheTableSql = db.prepare(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'generation_cache'`).get();
|
|
10817
|
+
const hasTokenMappingEntityType = genCacheTableSql?.sql.includes("'token_mapping'") ?? true;
|
|
10818
|
+
if (!hasTokenMappingEntityType) {
|
|
10819
|
+
db.exec("BEGIN");
|
|
10820
|
+
try {
|
|
10821
|
+
db.exec(`
|
|
10822
|
+
CREATE TABLE generation_cache__new2 (
|
|
10823
|
+
input_hash TEXT NOT NULL,
|
|
10824
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
10825
|
+
entity_id TEXT NOT NULL,
|
|
10826
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
10827
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
10828
|
+
created_at TEXT NOT NULL,
|
|
10829
|
+
updated_at TEXT NOT NULL,
|
|
10830
|
+
prompt_hash TEXT NOT NULL DEFAULT '',
|
|
10831
|
+
PRIMARY KEY (input_hash, prompt_hash, entity_type, entity_id)
|
|
10832
|
+
);
|
|
10833
|
+
INSERT INTO generation_cache__new2
|
|
10834
|
+
(input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
10835
|
+
SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
10836
|
+
FROM generation_cache;
|
|
10837
|
+
DROP TABLE generation_cache;
|
|
10838
|
+
ALTER TABLE generation_cache__new2 RENAME TO generation_cache;
|
|
10839
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
10840
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
10841
|
+
`);
|
|
10842
|
+
db.exec("COMMIT");
|
|
10843
|
+
} catch (e) {
|
|
10844
|
+
db.exec("ROLLBACK");
|
|
10845
|
+
throw e;
|
|
10846
|
+
}
|
|
10847
|
+
}
|
|
10848
|
+
const hasCompositionCache = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='composition_cache'`).all();
|
|
10849
|
+
if (hasCompositionCache.length === 0) {
|
|
10850
|
+
db.exec(`
|
|
10851
|
+
CREATE TABLE composition_cache (
|
|
10852
|
+
input_hash TEXT NOT NULL,
|
|
10853
|
+
cli_version TEXT NOT NULL,
|
|
10854
|
+
agent_output TEXT NOT NULL,
|
|
10855
|
+
created_at TEXT NOT NULL,
|
|
10856
|
+
updated_at TEXT NOT NULL,
|
|
10857
|
+
PRIMARY KEY (input_hash, cli_version)
|
|
10858
|
+
);
|
|
10859
|
+
`);
|
|
10584
10860
|
}
|
|
10585
10861
|
}
|
|
10586
10862
|
function loadComponentReviewMetadata(db, sessionId2, componentName) {
|
|
@@ -11120,16 +11396,16 @@ function extractRelativeImportPaths(sourceText) {
|
|
|
11120
11396
|
return [...specifiers];
|
|
11121
11397
|
}
|
|
11122
11398
|
async function resolveRelativeImport(specifier, fromDir) {
|
|
11123
|
-
const basePath =
|
|
11399
|
+
const basePath = resolve9(fromDir, specifier);
|
|
11124
11400
|
const candidates = [
|
|
11125
11401
|
basePath,
|
|
11126
11402
|
...rewrittenSourcePaths(basePath),
|
|
11127
11403
|
...SIBLING_FILE_EXTENSIONS.map((ext) => `${basePath}${ext}`),
|
|
11128
|
-
...SIBLING_FILE_EXTENSIONS.map((ext) =>
|
|
11404
|
+
...SIBLING_FILE_EXTENSIONS.map((ext) => resolve9(basePath, `index${ext}`))
|
|
11129
11405
|
];
|
|
11130
11406
|
for (const candidate of candidates) {
|
|
11131
11407
|
try {
|
|
11132
|
-
await
|
|
11408
|
+
await readFile8(candidate, "utf8");
|
|
11133
11409
|
return candidate;
|
|
11134
11410
|
} catch {
|
|
11135
11411
|
}
|
|
@@ -11145,7 +11421,7 @@ async function resolveImportSpecifiers(sourceText, fromDir) {
|
|
|
11145
11421
|
return resolvedPaths;
|
|
11146
11422
|
}
|
|
11147
11423
|
async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateTypeNames = []) {
|
|
11148
|
-
const visited = /* @__PURE__ */ new Set([
|
|
11424
|
+
const visited = /* @__PURE__ */ new Set([resolve9(sourcePath)]);
|
|
11149
11425
|
const discovered = [];
|
|
11150
11426
|
let frontier = [{ text: sourceText, dir: dirname14(sourcePath) }];
|
|
11151
11427
|
for (let hop = 0; hop < MAX_SIBLING_DEPTH && discovered.length < MAX_SIBLING_CANDIDATES_EXPLORED; hop++) {
|
|
@@ -11159,7 +11435,7 @@ async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateType
|
|
|
11159
11435
|
if (discovered.length >= MAX_SIBLING_CANDIDATES_EXPLORED) break;
|
|
11160
11436
|
let content;
|
|
11161
11437
|
try {
|
|
11162
|
-
content = await
|
|
11438
|
+
content = await readFile8(resolvedPath, "utf8");
|
|
11163
11439
|
} catch {
|
|
11164
11440
|
continue;
|
|
11165
11441
|
}
|
|
@@ -11196,7 +11472,7 @@ async function loadComponentSourceRef(name, sourcePath, propNames = [], propType
|
|
|
11196
11472
|
let truncatedSiblingCount = 0;
|
|
11197
11473
|
const usesNotShown = /* @__PURE__ */ new Set();
|
|
11198
11474
|
try {
|
|
11199
|
-
const rawText = await
|
|
11475
|
+
const rawText = await readFile8(sourcePath, "utf8");
|
|
11200
11476
|
let siblingUsesNotShown;
|
|
11201
11477
|
let declaredTypeNames;
|
|
11202
11478
|
({
|
|
@@ -11632,6 +11908,108 @@ function backfillUnclassifiedProps(db, sessionId2) {
|
|
|
11632
11908
|
).run(sessionId2, sessionId2);
|
|
11633
11909
|
return Number(withCategory.changes) + Number(withoutCategory.changes);
|
|
11634
11910
|
}
|
|
11911
|
+
function computeMapTokensInputHash(db, sessionId2, componentSourceRefs = []) {
|
|
11912
|
+
const props = db.prepare(
|
|
11913
|
+
`SELECT rc.name AS component_name, rp.name AS prop_name, rp.cdf_token_kind, rp.default_value
|
|
11914
|
+
FROM raw_props rp
|
|
11915
|
+
JOIN raw_components rc ON rc.session_id = rp.session_id AND rc.component_id = rp.component_id
|
|
11916
|
+
WHERE rp.session_id = ? AND rp.cdf_type = 'token' AND rp.cdf_category = 'design'
|
|
11917
|
+
ORDER BY rc.name, rp.name`
|
|
11918
|
+
).all(sessionId2);
|
|
11919
|
+
const tokens = db.prepare(`SELECT path, type FROM raw_tokens WHERE session_id = ? ORDER BY path`).all(sessionId2);
|
|
11920
|
+
const defaultMappings = db.prepare("SELECT raw_name, path, source FROM raw_token_name_paths WHERE session_id = ? ORDER BY raw_name").all(sessionId2);
|
|
11921
|
+
const payload = {
|
|
11922
|
+
props: props.map((p) => ({
|
|
11923
|
+
component: p.component_name,
|
|
11924
|
+
prop: p.prop_name,
|
|
11925
|
+
tokenKind: p.cdf_token_kind,
|
|
11926
|
+
rawDefault: p.default_value
|
|
11927
|
+
})),
|
|
11928
|
+
tokens,
|
|
11929
|
+
defaultMappings,
|
|
11930
|
+
// The agent's evidence, not just its inputs: a comment or allowlist edit
|
|
11931
|
+
// in a source file (or a sibling it reads) changes the correct answer
|
|
11932
|
+
// without touching props or tokens, so it must invalidate the cache too.
|
|
11933
|
+
sourceRefs: [...componentSourceRefs].sort((a, b) => a.component.localeCompare(b.component)).map((ref) => ({
|
|
11934
|
+
component: ref.component,
|
|
11935
|
+
content: ref.content,
|
|
11936
|
+
siblingFiles: (ref.siblingFiles ?? []).map((s) => ({ path: s.path, content: s.content })).sort((a, b) => a.path.localeCompare(b.path)),
|
|
11937
|
+
usesNotShown: [...ref.usesNotShown ?? []].sort()
|
|
11938
|
+
}))
|
|
11939
|
+
};
|
|
11940
|
+
return createHash5("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
11941
|
+
}
|
|
11942
|
+
function lookupCache(db, inputHash, entityType, entityId, promptHash = "") {
|
|
11943
|
+
const row = db.prepare(
|
|
11944
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11945
|
+
FROM generation_cache
|
|
11946
|
+
WHERE input_hash = ? AND entity_type = ? AND entity_id = ? AND prompt_hash = ?`
|
|
11947
|
+
).get(inputHash, entityType, entityId, promptHash);
|
|
11948
|
+
if (!row) return null;
|
|
11949
|
+
return {
|
|
11950
|
+
inputHash: row.input_hash,
|
|
11951
|
+
entityType: row.entity_type,
|
|
11952
|
+
entityId: row.entity_id,
|
|
11953
|
+
sourceSessionId: row.source_session_id,
|
|
11954
|
+
humanEdited: row.human_edited === 1,
|
|
11955
|
+
promptHash: row.prompt_hash,
|
|
11956
|
+
createdAt: row.created_at,
|
|
11957
|
+
updatedAt: row.updated_at
|
|
11958
|
+
};
|
|
11959
|
+
}
|
|
11960
|
+
function lookupCacheByEntity(db, entityType, entityId) {
|
|
11961
|
+
const row = db.prepare(
|
|
11962
|
+
`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
|
|
11963
|
+
FROM generation_cache
|
|
11964
|
+
WHERE entity_type = ? AND entity_id = ?
|
|
11965
|
+
ORDER BY updated_at DESC LIMIT 1`
|
|
11966
|
+
).get(entityType, entityId);
|
|
11967
|
+
if (!row) return null;
|
|
11968
|
+
return {
|
|
11969
|
+
inputHash: row.input_hash,
|
|
11970
|
+
entityType: row.entity_type,
|
|
11971
|
+
entityId: row.entity_id,
|
|
11972
|
+
sourceSessionId: row.source_session_id,
|
|
11973
|
+
humanEdited: row.human_edited === 1,
|
|
11974
|
+
promptHash: row.prompt_hash,
|
|
11975
|
+
createdAt: row.created_at,
|
|
11976
|
+
updatedAt: row.updated_at
|
|
11977
|
+
};
|
|
11978
|
+
}
|
|
11979
|
+
function storeCache(db, inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash = "") {
|
|
11980
|
+
storeCaches(db, [{ inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash }]);
|
|
11981
|
+
}
|
|
11982
|
+
function storeCaches(db, entries) {
|
|
11983
|
+
if (entries.length === 0) return;
|
|
11984
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11985
|
+
const insert = db.prepare(
|
|
11986
|
+
`INSERT INTO generation_cache (input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash)
|
|
11987
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
11988
|
+
ON CONFLICT(input_hash, prompt_hash, entity_type, entity_id) DO UPDATE SET
|
|
11989
|
+
source_session_id = excluded.source_session_id,
|
|
11990
|
+
human_edited = CASE WHEN generation_cache.human_edited = 1 THEN 1 ELSE excluded.human_edited END,
|
|
11991
|
+
updated_at = excluded.updated_at`
|
|
11992
|
+
);
|
|
11993
|
+
db.exec("BEGIN");
|
|
11994
|
+
try {
|
|
11995
|
+
for (const entry of entries) {
|
|
11996
|
+
insert.run(
|
|
11997
|
+
entry.inputHash,
|
|
11998
|
+
entry.entityType,
|
|
11999
|
+
entry.entityId,
|
|
12000
|
+
entry.sourceSessionId,
|
|
12001
|
+
entry.humanEdited ? 1 : 0,
|
|
12002
|
+
now,
|
|
12003
|
+
now,
|
|
12004
|
+
entry.promptHash ?? ""
|
|
12005
|
+
);
|
|
12006
|
+
}
|
|
12007
|
+
db.exec("COMMIT");
|
|
12008
|
+
} catch (e) {
|
|
12009
|
+
db.exec("ROLLBACK");
|
|
12010
|
+
throw e;
|
|
12011
|
+
}
|
|
12012
|
+
}
|
|
11635
12013
|
function storeScannedFiles(db, sessionId2, filePaths) {
|
|
11636
12014
|
db.exec("BEGIN");
|
|
11637
12015
|
try {
|
|
@@ -11714,7 +12092,105 @@ function filterUnknownSlotAllowedComponents(db, sessionId2, allowedComponentName
|
|
|
11714
12092
|
}
|
|
11715
12093
|
return unknown;
|
|
11716
12094
|
}
|
|
11717
|
-
function
|
|
12095
|
+
function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentId, manageTransaction = true, options = {}) {
|
|
12096
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12097
|
+
if (manageTransaction) db.exec("BEGIN");
|
|
12098
|
+
try {
|
|
12099
|
+
const srcComp = db.prepare(
|
|
12100
|
+
`SELECT description, status, component_description_rationale, props_rationale, slots_rationale
|
|
12101
|
+
FROM raw_components WHERE session_id = ? AND component_id = ?`
|
|
12102
|
+
).get(sourceSessionId, componentId);
|
|
12103
|
+
if (srcComp) {
|
|
12104
|
+
db.prepare(
|
|
12105
|
+
`UPDATE raw_components
|
|
12106
|
+
SET description = ?, status = ?, component_description_rationale = ?, props_rationale = ?, slots_rationale = ?, extracted_at = ?
|
|
12107
|
+
WHERE session_id = ? AND component_id = ?`
|
|
12108
|
+
).run(
|
|
12109
|
+
srcComp.description,
|
|
12110
|
+
srcComp.status,
|
|
12111
|
+
srcComp.component_description_rationale,
|
|
12112
|
+
srcComp.props_rationale,
|
|
12113
|
+
srcComp.slots_rationale,
|
|
12114
|
+
now,
|
|
12115
|
+
targetSessionId,
|
|
12116
|
+
componentId
|
|
12117
|
+
);
|
|
12118
|
+
}
|
|
12119
|
+
const srcProps = db.prepare(
|
|
12120
|
+
`SELECT name, cdf_type, cdf_category, cdf_token_kind, required, description, default_value, rationale
|
|
12121
|
+
FROM raw_props WHERE session_id = ? AND component_id = ?`
|
|
12122
|
+
).all(sourceSessionId, componentId);
|
|
12123
|
+
for (const p of srcProps) {
|
|
12124
|
+
db.prepare(
|
|
12125
|
+
`UPDATE raw_props SET cdf_type = ?, cdf_category = ?, cdf_token_kind = ?, required = ?, description = ?, default_value = ?, rationale = ?
|
|
12126
|
+
WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12127
|
+
).run(
|
|
12128
|
+
p.cdf_type,
|
|
12129
|
+
p.cdf_category,
|
|
12130
|
+
p.cdf_token_kind,
|
|
12131
|
+
p.required,
|
|
12132
|
+
p.description,
|
|
12133
|
+
p.default_value,
|
|
12134
|
+
p.rationale,
|
|
12135
|
+
targetSessionId,
|
|
12136
|
+
componentId,
|
|
12137
|
+
p.name
|
|
12138
|
+
);
|
|
12139
|
+
}
|
|
12140
|
+
db.prepare(`DELETE FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`).run(
|
|
12141
|
+
targetSessionId,
|
|
12142
|
+
componentId
|
|
12143
|
+
);
|
|
12144
|
+
const srcAV = db.prepare(
|
|
12145
|
+
`SELECT prop_name, position, value FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`
|
|
12146
|
+
).all(sourceSessionId, componentId);
|
|
12147
|
+
const insertAV = db.prepare(
|
|
12148
|
+
`INSERT INTO raw_prop_allowed_values (session_id, component_id, prop_name, position, value) VALUES (?, ?, ?, ?, ?)`
|
|
12149
|
+
);
|
|
12150
|
+
for (const av of srcAV) {
|
|
12151
|
+
insertAV.run(targetSessionId, componentId, av.prop_name, av.position, av.value);
|
|
12152
|
+
}
|
|
12153
|
+
const srcSlots = db.prepare(`SELECT name, required, description, rationale FROM raw_slots WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
|
|
12154
|
+
for (const s of srcSlots) {
|
|
12155
|
+
db.prepare(
|
|
12156
|
+
`UPDATE raw_slots SET required = ?, description = ?, rationale = ? WHERE session_id = ? AND component_id = ? AND name = ?`
|
|
12157
|
+
).run(s.required, s.description, s.rationale, targetSessionId, componentId, s.name);
|
|
12158
|
+
}
|
|
12159
|
+
db.prepare(`DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`).run(
|
|
12160
|
+
targetSessionId,
|
|
12161
|
+
componentId
|
|
12162
|
+
);
|
|
12163
|
+
const srcSAC = db.prepare(
|
|
12164
|
+
`SELECT slot_name, position, allowed_component FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`
|
|
12165
|
+
).all(sourceSessionId, componentId);
|
|
12166
|
+
const insertSAC = db.prepare(
|
|
12167
|
+
`INSERT INTO raw_slot_allowed_components (session_id, component_id, slot_name, allowed_component, position) VALUES (?, ?, ?, ?, ?)`
|
|
12168
|
+
);
|
|
12169
|
+
const allowedSAC = options.allowedComponentNames ? srcSAC.filter((sac) => options.allowedComponentNames.has(sac.allowed_component)) : srcSAC;
|
|
12170
|
+
for (const sac of allowedSAC) {
|
|
12171
|
+
insertSAC.run(targetSessionId, componentId, sac.slot_name, sac.allowed_component, sac.position);
|
|
12172
|
+
}
|
|
12173
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12174
|
+
if (manageTransaction) db.exec("COMMIT");
|
|
12175
|
+
} catch (e) {
|
|
12176
|
+
if (manageTransaction) db.exec("ROLLBACK");
|
|
12177
|
+
throw e;
|
|
12178
|
+
}
|
|
12179
|
+
}
|
|
12180
|
+
function copyComponentsFromCache(db, entries, options = {}) {
|
|
12181
|
+
if (entries.length === 0) return;
|
|
12182
|
+
db.exec("BEGIN");
|
|
12183
|
+
try {
|
|
12184
|
+
for (const entry of entries) {
|
|
12185
|
+
copyComponentFromCache(db, entry.sourceSessionId, entry.targetSessionId, entry.componentId, false, options);
|
|
12186
|
+
}
|
|
12187
|
+
db.exec("COMMIT");
|
|
12188
|
+
} catch (e) {
|
|
12189
|
+
db.exec("ROLLBACK");
|
|
12190
|
+
throw e;
|
|
12191
|
+
}
|
|
12192
|
+
}
|
|
12193
|
+
function copyTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
11718
12194
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11719
12195
|
db.exec("BEGIN");
|
|
11720
12196
|
try {
|
|
@@ -11735,7 +12211,139 @@ function copyTokensBetweenSessions(db, sourceSessionId, targetSessionId) {
|
|
|
11735
12211
|
throw e;
|
|
11736
12212
|
}
|
|
11737
12213
|
}
|
|
11738
|
-
|
|
12214
|
+
function copyMapTokensFromCache(db, sourceSessionId, targetSessionId) {
|
|
12215
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12216
|
+
let copiedCount = 0;
|
|
12217
|
+
db.exec("BEGIN");
|
|
12218
|
+
try {
|
|
12219
|
+
const sourceRows = db.prepare(
|
|
12220
|
+
`SELECT rc.name AS component_name, rptp.prop_name, rptp.source, rptp.position, rptp.path
|
|
12221
|
+
FROM raw_prop_token_paths rptp
|
|
12222
|
+
JOIN raw_components rc ON rc.session_id = rptp.session_id AND rc.component_id = rptp.component_id
|
|
12223
|
+
WHERE rptp.session_id = ?
|
|
12224
|
+
ORDER BY rc.name, rptp.prop_name, rptp.position`
|
|
12225
|
+
).all(sourceSessionId);
|
|
12226
|
+
const targetComponents = db.prepare(`SELECT component_id, name FROM raw_components WHERE session_id = ?`).all(targetSessionId);
|
|
12227
|
+
const targetIdByName = new Map(targetComponents.map((c2) => [c2.name, c2.component_id]));
|
|
12228
|
+
const targetProps = new Set(
|
|
12229
|
+
db.prepare(`SELECT component_id, name FROM raw_props WHERE session_id = ?`).all(targetSessionId).map((p) => `${p.component_id}::${p.name}`)
|
|
12230
|
+
);
|
|
12231
|
+
const insertPath = db.prepare(
|
|
12232
|
+
`INSERT INTO raw_prop_token_paths (session_id, component_id, prop_name, source, position, path)
|
|
12233
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
12234
|
+
);
|
|
12235
|
+
const clearedProps = /* @__PURE__ */ new Set();
|
|
12236
|
+
const copiedProps = /* @__PURE__ */ new Set();
|
|
12237
|
+
for (const row of sourceRows) {
|
|
12238
|
+
const targetComponentId = targetIdByName.get(row.component_name);
|
|
12239
|
+
if (!targetComponentId) continue;
|
|
12240
|
+
if (!targetProps.has(`${targetComponentId}::${row.prop_name}`)) continue;
|
|
12241
|
+
const propKey = `${targetComponentId}::${row.prop_name}`;
|
|
12242
|
+
if (!clearedProps.has(propKey)) {
|
|
12243
|
+
clearedProps.add(propKey);
|
|
12244
|
+
db.prepare(`DELETE FROM raw_prop_token_paths WHERE session_id = ? AND component_id = ? AND prop_name = ?`).run(
|
|
12245
|
+
targetSessionId,
|
|
12246
|
+
targetComponentId,
|
|
12247
|
+
row.prop_name
|
|
12248
|
+
);
|
|
12249
|
+
}
|
|
12250
|
+
insertPath.run(targetSessionId, targetComponentId, row.prop_name, row.source, row.position, row.path);
|
|
12251
|
+
copiedProps.add(propKey);
|
|
12252
|
+
}
|
|
12253
|
+
copiedCount = copiedProps.size;
|
|
12254
|
+
db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
|
|
12255
|
+
db.exec("COMMIT");
|
|
12256
|
+
} catch (e) {
|
|
12257
|
+
db.exec("ROLLBACK");
|
|
12258
|
+
throw e;
|
|
12259
|
+
}
|
|
12260
|
+
return copiedCount;
|
|
12261
|
+
}
|
|
12262
|
+
async function getCliCacheVersion() {
|
|
12263
|
+
if (_cliCacheVersionCache) return _cliCacheVersionCache;
|
|
12264
|
+
try {
|
|
12265
|
+
const { hashContent: hashContent2 } = await Promise.resolve().then(() => (init_cache_keys(), cache_keys_exports));
|
|
12266
|
+
const { resolveSkillPath: resolveSkillPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
12267
|
+
const skills = ["components", "tokens", "select"];
|
|
12268
|
+
const parts = [];
|
|
12269
|
+
for (const s of skills) {
|
|
12270
|
+
try {
|
|
12271
|
+
const p = resolveSkillPath2(s);
|
|
12272
|
+
parts.push(readFileSync5(p, "utf8"));
|
|
12273
|
+
} catch {
|
|
12274
|
+
parts.push(`<missing:${s}>`);
|
|
12275
|
+
}
|
|
12276
|
+
}
|
|
12277
|
+
_cliCacheVersionCache = hashContent2(parts.join("\n---\n"));
|
|
12278
|
+
return _cliCacheVersionCache;
|
|
12279
|
+
} catch {
|
|
12280
|
+
_cliCacheVersionCache = "fallback";
|
|
12281
|
+
return _cliCacheVersionCache;
|
|
12282
|
+
}
|
|
12283
|
+
}
|
|
12284
|
+
function storeExtractCache(db, filePath, fileHash, cliVersion2, components) {
|
|
12285
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12286
|
+
const componentsJson = JSON.stringify(components);
|
|
12287
|
+
db.prepare(
|
|
12288
|
+
`INSERT INTO extract_cache (file_path, file_hash, cli_version, created_at, updated_at, components_json)
|
|
12289
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
12290
|
+
ON CONFLICT(file_hash, cli_version) DO UPDATE SET
|
|
12291
|
+
file_path = excluded.file_path,
|
|
12292
|
+
updated_at = excluded.updated_at,
|
|
12293
|
+
components_json = excluded.components_json`
|
|
12294
|
+
).run(filePath, fileHash, cliVersion2, now, now, componentsJson);
|
|
12295
|
+
}
|
|
12296
|
+
function lookupExtractCache(db, fileHash, cliVersion2) {
|
|
12297
|
+
const row = db.prepare(
|
|
12298
|
+
`SELECT file_path, file_hash, cli_version, created_at, updated_at, components_json
|
|
12299
|
+
FROM extract_cache
|
|
12300
|
+
WHERE file_hash = ? AND cli_version = ?`
|
|
12301
|
+
).get(fileHash, cliVersion2);
|
|
12302
|
+
if (!row) return null;
|
|
12303
|
+
let components = [];
|
|
12304
|
+
try {
|
|
12305
|
+
components = JSON.parse(row.components_json);
|
|
12306
|
+
} catch {
|
|
12307
|
+
return null;
|
|
12308
|
+
}
|
|
12309
|
+
return {
|
|
12310
|
+
filePath: row.file_path,
|
|
12311
|
+
fileHash: row.file_hash,
|
|
12312
|
+
cliVersion: row.cli_version,
|
|
12313
|
+
createdAt: row.created_at,
|
|
12314
|
+
updatedAt: row.updated_at,
|
|
12315
|
+
components
|
|
12316
|
+
};
|
|
12317
|
+
}
|
|
12318
|
+
function storeSelectCache(db, componentHash, promptHash, cliVersion2, decision, reason) {
|
|
12319
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12320
|
+
db.prepare(
|
|
12321
|
+
`INSERT INTO select_cache (component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at)
|
|
12322
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
12323
|
+
ON CONFLICT(component_hash, prompt_hash, cli_version) DO UPDATE SET
|
|
12324
|
+
decision = excluded.decision,
|
|
12325
|
+
reason = excluded.reason,
|
|
12326
|
+
updated_at = excluded.updated_at`
|
|
12327
|
+
).run(componentHash, promptHash, cliVersion2, decision, reason, now, now);
|
|
12328
|
+
}
|
|
12329
|
+
function lookupSelectCache(db, componentHash, promptHash, cliVersion2) {
|
|
12330
|
+
const row = db.prepare(
|
|
12331
|
+
`SELECT component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at
|
|
12332
|
+
FROM select_cache
|
|
12333
|
+
WHERE component_hash = ? AND prompt_hash = ? AND cli_version = ?`
|
|
12334
|
+
).get(componentHash, promptHash, cliVersion2);
|
|
12335
|
+
if (!row) return null;
|
|
12336
|
+
return {
|
|
12337
|
+
componentHash: row.component_hash,
|
|
12338
|
+
promptHash: row.prompt_hash,
|
|
12339
|
+
cliVersion: row.cli_version,
|
|
12340
|
+
decision: row.decision,
|
|
12341
|
+
reason: row.reason,
|
|
12342
|
+
createdAt: row.created_at,
|
|
12343
|
+
updatedAt: row.updated_at
|
|
12344
|
+
};
|
|
12345
|
+
}
|
|
12346
|
+
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;
|
|
11739
12347
|
var init_db = __esm({
|
|
11740
12348
|
"packages/experience-design-system-cli-legacy/src/session/db.ts"() {
|
|
11741
12349
|
"use strict";
|
|
@@ -11749,6 +12357,8 @@ var init_db = __esm({
|
|
|
11749
12357
|
init_write2();
|
|
11750
12358
|
init_session_resolver();
|
|
11751
12359
|
init_read3();
|
|
12360
|
+
init_hash_component_shape();
|
|
12361
|
+
init_hash_token_content();
|
|
11752
12362
|
init_read3();
|
|
11753
12363
|
init_store_dtcg_tokens();
|
|
11754
12364
|
init_apply_tool_calls();
|
|
@@ -11872,6 +12482,17 @@ CREATE TABLE IF NOT EXISTS raw_tokens (
|
|
|
11872
12482
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
11873
12483
|
);
|
|
11874
12484
|
|
|
12485
|
+
CREATE TABLE IF NOT EXISTS generation_cache (
|
|
12486
|
+
input_hash TEXT NOT NULL,
|
|
12487
|
+
entity_type TEXT NOT NULL CHECK (entity_type IN ('component', 'token_set', 'token_mapping')),
|
|
12488
|
+
entity_id TEXT NOT NULL,
|
|
12489
|
+
source_session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
12490
|
+
human_edited INTEGER NOT NULL DEFAULT 0 CHECK (human_edited IN (0, 1)),
|
|
12491
|
+
created_at TEXT NOT NULL,
|
|
12492
|
+
updated_at TEXT NOT NULL,
|
|
12493
|
+
PRIMARY KEY (input_hash, entity_type, entity_id)
|
|
12494
|
+
);
|
|
12495
|
+
|
|
11875
12496
|
CREATE TABLE IF NOT EXISTS scanned_files (
|
|
11876
12497
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
11877
12498
|
path TEXT NOT NULL,
|
|
@@ -11917,9 +12538,10 @@ CREATE INDEX IF NOT EXISTS idx_raw_props_session ON raw_props(session_id,
|
|
|
11917
12538
|
CREATE INDEX IF NOT EXISTS idx_raw_slots_session ON raw_slots(session_id, component_id);
|
|
11918
12539
|
CREATE INDEX IF NOT EXISTS idx_raw_tokens_session ON raw_tokens(session_id);
|
|
11919
12540
|
CREATE INDEX IF NOT EXISTS idx_raw_token_groups_session ON raw_token_groups(session_id);
|
|
12541
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_entity ON generation_cache(entity_type, entity_id);
|
|
12542
|
+
CREATE INDEX IF NOT EXISTS idx_generation_cache_session ON generation_cache(source_session_id);
|
|
11920
12543
|
CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session_id);
|
|
11921
12544
|
`;
|
|
11922
|
-
REMOVED_CACHE_TABLES = ["generation_cache", "extract_cache", "composition_cache", "select_cache"];
|
|
11923
12545
|
MAX_COMPONENT_SOURCE_CHARS = 8e3;
|
|
11924
12546
|
MAX_SIBLING_FILES = 5;
|
|
11925
12547
|
MAX_SIBLING_SNIPPET_CHARS = 1200;
|
|
@@ -11936,15 +12558,16 @@ CREATE INDEX IF NOT EXISTS idx_scanned_files_session ON scanned_files(session
|
|
|
11936
12558
|
[".cjs", [".cts", ".cjs"]]
|
|
11937
12559
|
];
|
|
11938
12560
|
IDENTIFIER_PATTERN = /[A-Za-z_$][A-Za-z0-9_$]*/g;
|
|
12561
|
+
_cliCacheVersionCache = null;
|
|
11939
12562
|
}
|
|
11940
12563
|
});
|
|
11941
12564
|
|
|
11942
12565
|
// packages/experience-design-system-cli-legacy/src/helpers/read-existing-contentful-entities-from-session.ts
|
|
11943
|
-
import { readFile as
|
|
12566
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
11944
12567
|
async function readExistingContentfulEntitiesFromSession(path) {
|
|
11945
12568
|
if (!path) return void 0;
|
|
11946
12569
|
try {
|
|
11947
|
-
const raw = await
|
|
12570
|
+
const raw = await readFile9(path, "utf8");
|
|
11948
12571
|
const parsed = JSON.parse(raw);
|
|
11949
12572
|
if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens)) return void 0;
|
|
11950
12573
|
return parsed;
|
|
@@ -12068,21 +12691,21 @@ var init_resolve_session_id = __esm({
|
|
|
12068
12691
|
});
|
|
12069
12692
|
|
|
12070
12693
|
// packages/experience-design-system-cli-legacy/src/analyze/select/persistence.ts
|
|
12071
|
-
import { access, appendFile, mkdir as mkdir2, readFile as
|
|
12694
|
+
import { access, appendFile, mkdir as mkdir2, readFile as readFile10, writeFile as writeFile2 } from "node:fs/promises";
|
|
12072
12695
|
import { homedir as homedir4 } from "node:os";
|
|
12073
|
-
import { resolve as
|
|
12696
|
+
import { resolve as resolve10 } from "node:path";
|
|
12074
12697
|
function getRefineArtifactsRoot() {
|
|
12075
12698
|
if (process.env.EDS_REVIEW_ARTIFACTS_DIR) {
|
|
12076
|
-
return
|
|
12699
|
+
return resolve10(process.env.EDS_REVIEW_ARTIFACTS_DIR);
|
|
12077
12700
|
}
|
|
12078
|
-
return
|
|
12701
|
+
return resolve10(homedir4(), ".contentful", "experience-design-system-cli", "reviews");
|
|
12079
12702
|
}
|
|
12080
12703
|
async function getRefineSessionPaths(sessionId2, artifactsRoot) {
|
|
12081
|
-
const sessionDir =
|
|
12704
|
+
const sessionDir = resolve10(artifactsRoot, sessionId2);
|
|
12082
12705
|
return {
|
|
12083
12706
|
sessionDir,
|
|
12084
|
-
eventsPath:
|
|
12085
|
-
statePath:
|
|
12707
|
+
eventsPath: resolve10(sessionDir, "events.jsonl"),
|
|
12708
|
+
statePath: resolve10(sessionDir, "current-review-state.json")
|
|
12086
12709
|
};
|
|
12087
12710
|
}
|
|
12088
12711
|
async function saveReviewState(statePath, session) {
|
|
@@ -12093,7 +12716,7 @@ async function ensureRefineSession(sessionId2, artifactsRoot, initialSnapshot) {
|
|
|
12093
12716
|
await mkdir2(paths.sessionDir, { recursive: true });
|
|
12094
12717
|
try {
|
|
12095
12718
|
await access(paths.statePath);
|
|
12096
|
-
const savedState = await
|
|
12719
|
+
const savedState = await readFile10(paths.statePath, "utf8");
|
|
12097
12720
|
return JSON.parse(savedState);
|
|
12098
12721
|
} catch {
|
|
12099
12722
|
await writeFile2(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
|
|
@@ -12578,8 +13201,8 @@ var init_path_exists = __esm({
|
|
|
12578
13201
|
});
|
|
12579
13202
|
|
|
12580
13203
|
// packages/experience-design-system-cli-legacy/src/lib/prompt-overrides.ts
|
|
12581
|
-
import { readFile as
|
|
12582
|
-
import { resolve as
|
|
13204
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
13205
|
+
import { resolve as resolve11 } from "node:path";
|
|
12583
13206
|
function looksLikePath(value) {
|
|
12584
13207
|
if (value.includes("/") || value.includes("\\")) return true;
|
|
12585
13208
|
if (value.startsWith("~")) return true;
|
|
@@ -12611,9 +13234,9 @@ function parsePromptOverrides(inputs) {
|
|
|
12611
13234
|
}
|
|
12612
13235
|
async function resolvePromptOverride(override) {
|
|
12613
13236
|
if (override.kind === "text") return override.value;
|
|
12614
|
-
const abs =
|
|
13237
|
+
const abs = resolve11(override.value);
|
|
12615
13238
|
try {
|
|
12616
|
-
return await
|
|
13239
|
+
return await readFile11(abs, "utf8");
|
|
12617
13240
|
} catch {
|
|
12618
13241
|
throw new Error(`--prompt: could not read prompt file: ${abs}`);
|
|
12619
13242
|
}
|
|
@@ -12628,21 +13251,21 @@ var init_prompt_overrides = __esm({
|
|
|
12628
13251
|
|
|
12629
13252
|
// packages/experience-design-system-cli-legacy/src/generate/command.ts
|
|
12630
13253
|
import { createElement } from "react";
|
|
12631
|
-
import { readFile as
|
|
12632
|
-
import { join as join14, resolve as
|
|
13254
|
+
import { readFile as readFile12, readdir, stat } from "node:fs/promises";
|
|
13255
|
+
import { join as join14, resolve as resolve12 } from "node:path";
|
|
12633
13256
|
async function assertFileExists(flag, p) {
|
|
12634
13257
|
if (!await pathExists(p)) die(`Error: file not found: ${p} (from ${flag})`);
|
|
12635
13258
|
}
|
|
12636
13259
|
async function readFileInline(path) {
|
|
12637
13260
|
if (!path) return void 0;
|
|
12638
|
-
const resolved =
|
|
13261
|
+
const resolved = resolve12(path);
|
|
12639
13262
|
let s;
|
|
12640
13263
|
try {
|
|
12641
13264
|
s = await stat(resolved);
|
|
12642
13265
|
} catch {
|
|
12643
13266
|
return void 0;
|
|
12644
13267
|
}
|
|
12645
|
-
if (!s.isDirectory()) return
|
|
13268
|
+
if (!s.isDirectory()) return readFile12(resolved, "utf8");
|
|
12646
13269
|
const files = [];
|
|
12647
13270
|
async function walk(dir) {
|
|
12648
13271
|
let entries;
|
|
@@ -12668,7 +13291,7 @@ async function readFileInline(path) {
|
|
|
12668
13291
|
}
|
|
12669
13292
|
await walk(resolved);
|
|
12670
13293
|
if (files.length === 0) return void 0;
|
|
12671
|
-
const parts = await Promise.all(files.map((f) =>
|
|
13294
|
+
const parts = await Promise.all(files.map((f) => readFile12(f, "utf8").catch(() => "")));
|
|
12672
13295
|
return parts.filter(Boolean).join("\n\n");
|
|
12673
13296
|
}
|
|
12674
13297
|
function printFallbackInstructions(options) {
|
|
@@ -12690,6 +13313,23 @@ function printFallbackInstructions(options) {
|
|
|
12690
13313
|
lines.push(` Re-run the generate command with the agent available, or use --dry-run to inspect the prompt.`);
|
|
12691
13314
|
process.stderr.write(lines.join("\n") + "\n");
|
|
12692
13315
|
}
|
|
13316
|
+
function createCachedComponentResult(componentName, warnings = []) {
|
|
13317
|
+
return {
|
|
13318
|
+
componentName,
|
|
13319
|
+
classified: 0,
|
|
13320
|
+
excluded: 0,
|
|
13321
|
+
slots: 0,
|
|
13322
|
+
warnings,
|
|
13323
|
+
failed: false,
|
|
13324
|
+
cached: true,
|
|
13325
|
+
renamedSlotsCount: 0
|
|
13326
|
+
};
|
|
13327
|
+
}
|
|
13328
|
+
function writeCachedComponentStatus(position, componentName, pinned) {
|
|
13329
|
+
const status = pinned ? c.cyan("pinned (human-edited)") : c.green("cached");
|
|
13330
|
+
process.stderr.write(` ${position} ${c.bold(componentName)} ${status}
|
|
13331
|
+
`);
|
|
13332
|
+
}
|
|
12693
13333
|
async function showGenerateView(result) {
|
|
12694
13334
|
if (process.stdout.isTTY) {
|
|
12695
13335
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -12710,6 +13350,29 @@ session=${result.sessionId}
|
|
|
12710
13350
|
);
|
|
12711
13351
|
await exitWithAnalytics(0);
|
|
12712
13352
|
}
|
|
13353
|
+
function normalizeComponentForCache(component) {
|
|
13354
|
+
const slots = component.slots.map((slot, index, allSlots) => ({
|
|
13355
|
+
...slot,
|
|
13356
|
+
name: slot.name.trim() || (allSlots.length === 1 ? "children" : `slot_${index}`)
|
|
13357
|
+
}));
|
|
13358
|
+
return { ...component, slots };
|
|
13359
|
+
}
|
|
13360
|
+
function lookupComponentCache(db, component, promptHash) {
|
|
13361
|
+
const normalized = normalizeComponentForCache(component);
|
|
13362
|
+
const inputHash = hashComponentShape(normalized);
|
|
13363
|
+
const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
|
|
13364
|
+
if (cached) return cached;
|
|
13365
|
+
const legacyInputHash = hashComponentShape(component);
|
|
13366
|
+
return legacyInputHash === inputHash ? null : lookupCache(db, legacyInputHash, "component", component.component_id, promptHash);
|
|
13367
|
+
}
|
|
13368
|
+
function resolveComponentCache(db, component, promptHash, allowedComponentNames2) {
|
|
13369
|
+
const cached = lookupComponentCache(db, component, promptHash);
|
|
13370
|
+
if (cached && findUnknownSlotAllowedComponents(db, cached.sourceSessionId, allowedComponentNames2, component.component_id).length === 0) {
|
|
13371
|
+
return { entry: cached, humanEdited: cached.humanEdited };
|
|
13372
|
+
}
|
|
13373
|
+
const pinned = lookupCacheByEntity(db, "component", component.component_id);
|
|
13374
|
+
return pinned?.humanEdited && findUnknownSlotAllowedComponents(db, pinned.sourceSessionId, allowedComponentNames2, component.component_id).length === 0 ? { entry: pinned, humanEdited: true } : null;
|
|
13375
|
+
}
|
|
12713
13376
|
async function runOneComponent(options, component, index, total) {
|
|
12714
13377
|
const {
|
|
12715
13378
|
agent,
|
|
@@ -12719,10 +13382,13 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12719
13382
|
tokensInline,
|
|
12720
13383
|
tokenMapInline,
|
|
12721
13384
|
verbose,
|
|
13385
|
+
noCache,
|
|
12722
13386
|
skillPathOverride,
|
|
12723
13387
|
skillContentOverride,
|
|
13388
|
+
promptHash,
|
|
12724
13389
|
existingContentfulEntities,
|
|
12725
13390
|
existingTokensInline,
|
|
13391
|
+
precomputedCachedNames,
|
|
12726
13392
|
allowedComponentNames: allowedComponentNames2
|
|
12727
13393
|
} = options;
|
|
12728
13394
|
const pos = c.dim(`[${index + 1}/${total}]`);
|
|
@@ -12747,6 +13413,40 @@ async function runOneComponent(options, component, index, total) {
|
|
|
12747
13413
|
allowedComponents: slot.allowedComponents.filter((name) => allowedComponentNames2.has(name))
|
|
12748
13414
|
};
|
|
12749
13415
|
});
|
|
13416
|
+
const cacheComponent = normalizeComponentForCache(component);
|
|
13417
|
+
if (!noCache && precomputedCachedNames.has(component.name)) {
|
|
13418
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13419
|
+
return createCachedComponentResult(component.name);
|
|
13420
|
+
}
|
|
13421
|
+
if (!noCache) {
|
|
13422
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13423
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13424
|
+
if (resolution && !resolution.humanEdited) {
|
|
13425
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13426
|
+
allowedComponentNames: allowedComponentNames2
|
|
13427
|
+
});
|
|
13428
|
+
storeCache(
|
|
13429
|
+
db,
|
|
13430
|
+
inputHash,
|
|
13431
|
+
"component",
|
|
13432
|
+
component.component_id,
|
|
13433
|
+
resolution.entry.sourceSessionId,
|
|
13434
|
+
resolution.entry.humanEdited,
|
|
13435
|
+
promptHash
|
|
13436
|
+
);
|
|
13437
|
+
writeCachedComponentStatus(pos, component.name, false);
|
|
13438
|
+
return createCachedComponentResult(component.name);
|
|
13439
|
+
}
|
|
13440
|
+
if (resolution?.humanEdited) {
|
|
13441
|
+
copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId2, component.component_id, true, {
|
|
13442
|
+
allowedComponentNames: allowedComponentNames2
|
|
13443
|
+
});
|
|
13444
|
+
writeCachedComponentStatus(pos, component.name, true);
|
|
13445
|
+
return createCachedComponentResult(`${component.name}`, [
|
|
13446
|
+
`${component.name}: source changed but human edits preserved`
|
|
13447
|
+
]);
|
|
13448
|
+
}
|
|
13449
|
+
}
|
|
12750
13450
|
const componentBuckets = bucketComponentProps(component);
|
|
12751
13451
|
getDebugLogger().event("analyze", "prop-buckets.generate", { ...componentBuckets });
|
|
12752
13452
|
const rawComponentsInline = JSON.stringify(
|
|
@@ -12821,6 +13521,10 @@ ${outputBuf}`);
|
|
|
12821
13521
|
const applied = applyToolCalls(db, sessionId2, component.component_id, component.name, calls, warnings, {
|
|
12822
13522
|
allowedComponentNames: allowedComponentNames2
|
|
12823
13523
|
});
|
|
13524
|
+
if (!noCache) {
|
|
13525
|
+
const inputHash = hashComponentShape(cacheComponent);
|
|
13526
|
+
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
13527
|
+
}
|
|
12824
13528
|
return {
|
|
12825
13529
|
componentName: component.name,
|
|
12826
13530
|
classified: applied.classified,
|
|
@@ -12872,7 +13576,7 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12872
13576
|
try {
|
|
12873
13577
|
const artifactsRoot = getRefineArtifactsRoot();
|
|
12874
13578
|
const paths = await getRefineSessionPaths(sessionId2, artifactsRoot);
|
|
12875
|
-
const raw = await
|
|
13579
|
+
const raw = await readFile12(paths.statePath, "utf8");
|
|
12876
13580
|
const snapshot = JSON.parse(raw);
|
|
12877
13581
|
const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
|
|
12878
13582
|
if (accepted.length === 0) return null;
|
|
@@ -12881,6 +13585,15 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
12881
13585
|
return null;
|
|
12882
13586
|
}
|
|
12883
13587
|
}
|
|
13588
|
+
function parsePrecomputedCachedNames(value) {
|
|
13589
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
13590
|
+
try {
|
|
13591
|
+
const parsed = JSON.parse(value);
|
|
13592
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((name) => typeof name === "string") : []);
|
|
13593
|
+
} catch {
|
|
13594
|
+
return /* @__PURE__ */ new Set();
|
|
13595
|
+
}
|
|
13596
|
+
}
|
|
12884
13597
|
async function runGenerateSkill(skill, opts, verbose = false) {
|
|
12885
13598
|
const savedCreds = await readExperiencesCredentials();
|
|
12886
13599
|
const agentName = opts.agent ?? savedCreds.agent;
|
|
@@ -12909,8 +13622,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12909
13622
|
}
|
|
12910
13623
|
const generatePromptPath = generatePrompt === void 0 ? configuredGeneratePromptPath : void 0;
|
|
12911
13624
|
if (generatePromptPath) {
|
|
12912
|
-
if (!await pathExists(
|
|
12913
|
-
die(`Error: custom prompt path not found: ${
|
|
13625
|
+
if (!await pathExists(resolve12(generatePromptPath))) {
|
|
13626
|
+
die(`Error: custom prompt path not found: ${resolve12(generatePromptPath)}`);
|
|
12914
13627
|
}
|
|
12915
13628
|
if (!generatePromptPath.toLowerCase().endsWith(".md")) {
|
|
12916
13629
|
process.stderr.write(
|
|
@@ -12918,7 +13631,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12918
13631
|
`
|
|
12919
13632
|
);
|
|
12920
13633
|
}
|
|
12921
|
-
process.stderr.write(formatCustomPromptBanner("components",
|
|
13634
|
+
process.stderr.write(formatCustomPromptBanner("components", resolve12(generatePromptPath)));
|
|
12922
13635
|
}
|
|
12923
13636
|
if (skill === "tokens" && !opts.rawTokens) {
|
|
12924
13637
|
die("Error: --raw-tokens is required when using generate tokens");
|
|
@@ -12934,7 +13647,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
12934
13647
|
let existingContentfulEntities;
|
|
12935
13648
|
let existingTokensInline;
|
|
12936
13649
|
if (opts.existingEntitiesPath) {
|
|
12937
|
-
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
13650
|
+
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(resolve12(opts.existingEntitiesPath));
|
|
12938
13651
|
if (existingContentfulEntities) {
|
|
12939
13652
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
12940
13653
|
} else {
|
|
@@ -13035,7 +13748,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13035
13748
|
rawComponentsInline: sampleInline ?? rawTokensInline,
|
|
13036
13749
|
propBucketsInline: sampleBuckets ? JSON.stringify(sampleBuckets) : void 0,
|
|
13037
13750
|
rawTokensInline: skill === "tokens" ? rawTokensInline : void 0,
|
|
13038
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13751
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13039
13752
|
tokensInline,
|
|
13040
13753
|
tokenMapInline,
|
|
13041
13754
|
outDir: process.cwd(),
|
|
@@ -13061,7 +13774,64 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13061
13774
|
if (skill === "components" && allComponents && sessionId2) {
|
|
13062
13775
|
const db = openPipelineDb();
|
|
13063
13776
|
let componentResults;
|
|
13777
|
+
const precomputedCachedNames = parsePrecomputedCachedNames(opts.cachedComponents);
|
|
13064
13778
|
try {
|
|
13779
|
+
const existingContentfulEntitiesHashInputs = [];
|
|
13780
|
+
if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
|
|
13781
|
+
const promptHash = await hashPromptForSkill(
|
|
13782
|
+
"components",
|
|
13783
|
+
agent,
|
|
13784
|
+
model,
|
|
13785
|
+
generatePromptPath,
|
|
13786
|
+
existingContentfulEntitiesHashInputs,
|
|
13787
|
+
generatePrompt
|
|
13788
|
+
);
|
|
13789
|
+
if (opts.cacheStatus) {
|
|
13790
|
+
const cacheEnabled = opts.cache !== false && process.env.EDS_NO_CACHE !== "1";
|
|
13791
|
+
const cachedComponents = cacheEnabled ? allComponents.flatMap((component) => {
|
|
13792
|
+
const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
|
|
13793
|
+
return resolution ? [{ component, resolution }] : [];
|
|
13794
|
+
}) : [];
|
|
13795
|
+
if (cacheEnabled && opts.restoreCache) {
|
|
13796
|
+
const restorations = [];
|
|
13797
|
+
const rekeyed = [];
|
|
13798
|
+
const componentStatus = db.prepare(
|
|
13799
|
+
"SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?"
|
|
13800
|
+
);
|
|
13801
|
+
for (const { component, resolution } of cachedComponents) {
|
|
13802
|
+
const current = componentStatus.get(sessionId2, component.component_id);
|
|
13803
|
+
if (current?.status === "generated") continue;
|
|
13804
|
+
renameEmptySlots(db, sessionId2, component.component_id, component.name, component.slots.length);
|
|
13805
|
+
restorations.push({
|
|
13806
|
+
sourceSessionId: resolution.entry.sourceSessionId,
|
|
13807
|
+
targetSessionId: sessionId2,
|
|
13808
|
+
componentId: component.component_id
|
|
13809
|
+
});
|
|
13810
|
+
rekeyed.push({ component, cached: resolution.entry });
|
|
13811
|
+
}
|
|
13812
|
+
copyComponentsFromCache(db, restorations, { allowedComponentNames: allowedComponentNames2 });
|
|
13813
|
+
storeCaches(
|
|
13814
|
+
db,
|
|
13815
|
+
rekeyed.map(({ component, cached }) => ({
|
|
13816
|
+
inputHash: hashComponentShape(normalizeComponentForCache(component)),
|
|
13817
|
+
entityType: "component",
|
|
13818
|
+
entityId: component.component_id,
|
|
13819
|
+
sourceSessionId: cached.sourceSessionId,
|
|
13820
|
+
humanEdited: cached.humanEdited,
|
|
13821
|
+
promptHash
|
|
13822
|
+
}))
|
|
13823
|
+
);
|
|
13824
|
+
}
|
|
13825
|
+
const fullyCached = cacheEnabled && cachedComponents.length === allComponents.length;
|
|
13826
|
+
process.stdout.write(`cache-status=${fullyCached ? "hit" : "miss"}
|
|
13827
|
+
`);
|
|
13828
|
+
process.stdout.write(
|
|
13829
|
+
`cache-components=${JSON.stringify(cachedComponents.map(({ component }) => component.name))}
|
|
13830
|
+
`
|
|
13831
|
+
);
|
|
13832
|
+
await exitWithAnalytics(0);
|
|
13833
|
+
return;
|
|
13834
|
+
}
|
|
13065
13835
|
componentResults = await runAllComponents(
|
|
13066
13836
|
{
|
|
13067
13837
|
agent,
|
|
@@ -13071,10 +13841,13 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13071
13841
|
tokensInline,
|
|
13072
13842
|
tokenMapInline,
|
|
13073
13843
|
verbose,
|
|
13844
|
+
noCache: opts.cache === false || process.env.EDS_NO_CACHE === "1",
|
|
13074
13845
|
skillPathOverride: generatePromptPath,
|
|
13075
13846
|
skillContentOverride: generatePrompt,
|
|
13847
|
+
promptHash,
|
|
13076
13848
|
existingContentfulEntities,
|
|
13077
13849
|
existingTokensInline,
|
|
13850
|
+
precomputedCachedNames,
|
|
13078
13851
|
allowedComponentNames: allowedComponentNames2
|
|
13079
13852
|
},
|
|
13080
13853
|
allComponents
|
|
@@ -13083,7 +13856,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13083
13856
|
db.close();
|
|
13084
13857
|
}
|
|
13085
13858
|
const failed = componentResults.filter((r) => r.failed);
|
|
13086
|
-
const
|
|
13859
|
+
const cachedResults = componentResults.filter((r) => r.cached);
|
|
13860
|
+
const generated = componentResults.filter((r) => !r.failed && !r.cached);
|
|
13087
13861
|
const allWarnings = componentResults.flatMap((r) => r.warnings.map((w) => ` ${r.componentName}: ${w}`));
|
|
13088
13862
|
if (allWarnings.length > 0) {
|
|
13089
13863
|
process.stderr.write(c.yellow("Warnings:") + "\n" + allWarnings.join("\n") + "\n");
|
|
@@ -13099,17 +13873,21 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13099
13873
|
const totalExcluded = generated.reduce((s, r) => s + r.excluded, 0);
|
|
13100
13874
|
const totalRenamedSlots = componentResults.reduce((s, r) => s + r.renamedSlotsCount, 0);
|
|
13101
13875
|
const allOk = failed.length === 0;
|
|
13876
|
+
const cachedNote = cachedResults.length > 0 ? c.dim(` (${cachedResults.length} cached)`) : "";
|
|
13102
13877
|
process.stderr.write(
|
|
13103
|
-
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length}/${componentResults.length} components` + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13878
|
+
(allOk ? c.green("\u2713") : c.yellow("\u26A0")) + ` ${generated.length + cachedResults.length}/${componentResults.length} components` + cachedNote + c.dim(` ${totalClassified} classified, ${totalExcluded} unattached`) + "\n"
|
|
13104
13879
|
);
|
|
13105
13880
|
process.stdout.write(`renamed-slots: ${totalRenamedSlots}
|
|
13106
13881
|
`);
|
|
13107
|
-
if (generated.length === 0) {
|
|
13882
|
+
if (generated.length === 0 && cachedResults.length === 0) {
|
|
13108
13883
|
die(
|
|
13109
13884
|
`Error: all ${componentResults.length} component(s) failed to generate \u2014 see the per-component errors above.`
|
|
13110
13885
|
);
|
|
13111
13886
|
}
|
|
13112
13887
|
} else if (skill === "tokens") {
|
|
13888
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
13889
|
+
const tokenInputContent = rawTokensInline ?? "";
|
|
13890
|
+
const tokenInputHash = hashTokenContent(tokenInputContent);
|
|
13113
13891
|
const db = openPipelineDb();
|
|
13114
13892
|
try {
|
|
13115
13893
|
let resolvedSessionId = opts.session;
|
|
@@ -13136,11 +13914,26 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
13136
13914
|
}
|
|
13137
13915
|
sessionId2 = resolvedSessionId;
|
|
13138
13916
|
await bindAnalyticsSessionId(resolvedSessionId);
|
|
13917
|
+
const tokenPromptHash = await hashPromptForSkill("tokens", agent, model);
|
|
13918
|
+
if (!noCache) {
|
|
13919
|
+
const tokenCached = lookupCache(db, tokenInputHash, "token_set", "__tokens__", tokenPromptHash);
|
|
13920
|
+
if (tokenCached) {
|
|
13921
|
+
copyTokensFromCache(db, tokenCached.sourceSessionId, resolvedSessionId);
|
|
13922
|
+
sessionId2 = resolvedSessionId;
|
|
13923
|
+
process.stderr.write(
|
|
13924
|
+
`Done: tokens reused from cache ${c.dim(`(source: ${tokenCached.sourceSessionId.slice(0, 12)})`)}
|
|
13925
|
+
`
|
|
13926
|
+
);
|
|
13927
|
+
db.close();
|
|
13928
|
+
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13929
|
+
return;
|
|
13930
|
+
}
|
|
13931
|
+
}
|
|
13139
13932
|
const prompt = await buildPrompt({
|
|
13140
13933
|
skill,
|
|
13141
13934
|
mode: "autonomous",
|
|
13142
13935
|
rawTokensInline,
|
|
13143
|
-
rawTokensFilename: opts.rawTokens ?
|
|
13936
|
+
rawTokensFilename: opts.rawTokens ? resolve12(opts.rawTokens).split("/").pop() : void 0,
|
|
13144
13937
|
tokensInline,
|
|
13145
13938
|
tokenMapInline,
|
|
13146
13939
|
outDir: process.cwd()
|
|
@@ -13177,6 +13970,9 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13177
13970
|
`);
|
|
13178
13971
|
}
|
|
13179
13972
|
applyTokenToolCalls(db, resolvedSessionId, tokenCalls, []);
|
|
13973
|
+
if (!noCache) {
|
|
13974
|
+
storeCache(db, tokenInputHash, "token_set", "__tokens__", resolvedSessionId, false, tokenPromptHash);
|
|
13975
|
+
}
|
|
13180
13976
|
sessionId2 = resolvedSessionId;
|
|
13181
13977
|
const groupCount = tokenCalls.filter((tc) => tc.tool === "set_group").length;
|
|
13182
13978
|
process.stderr.write(`Done: ${tokenCount} tokens, ${groupCount} groups stored
|
|
@@ -13188,7 +13984,10 @@ ${tokenWarnings.map((w) => ` ${w}`).join("\n")}
|
|
|
13188
13984
|
await showGenerateView({ skill, agent, sessionId: sessionId2 ?? "" });
|
|
13189
13985
|
}
|
|
13190
13986
|
function addAgentFlags(cmd) {
|
|
13191
|
-
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent")
|
|
13987
|
+
return addAgentModelOptions(cmd).option("--verbose", "Show full agent output including reasoning text").option("--dry-run", "Print the prompt without invoking the agent").option(
|
|
13988
|
+
"--no-cache",
|
|
13989
|
+
"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."
|
|
13990
|
+
);
|
|
13192
13991
|
}
|
|
13193
13992
|
function registerInternalGenerateCommand(program) {
|
|
13194
13993
|
const generate = program.command("__generate", { hidden: true }).description("Internal import pipeline generation command");
|
|
@@ -13204,6 +14003,12 @@ function registerInternalGenerateCommand(program) {
|
|
|
13204
14003
|
"--existing-entities-path <path>",
|
|
13205
14004
|
"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."
|
|
13206
14005
|
);
|
|
14006
|
+
componentsCmd.option("--cache-status", "Check whether all selected component definitions are cached");
|
|
14007
|
+
componentsCmd.option("--restore-cache", "Restore cached component definitions into the current session");
|
|
14008
|
+
componentsCmd.option(
|
|
14009
|
+
"--cached-components <json>",
|
|
14010
|
+
"Component names already restored by a prior cache-status lookup; skip per-component cache lookup"
|
|
14011
|
+
);
|
|
13207
14012
|
addAgentFlags(componentsCmd).action(async (opts) => {
|
|
13208
14013
|
await runGenerateSkill("components", opts, opts.verbose ?? false);
|
|
13209
14014
|
});
|
|
@@ -13229,6 +14034,7 @@ var init_command = __esm({
|
|
|
13229
14034
|
init_agent_output();
|
|
13230
14035
|
init_GenerateView();
|
|
13231
14036
|
init_db();
|
|
14037
|
+
init_cache_keys();
|
|
13232
14038
|
init_read_existing_contentful_entities_from_session();
|
|
13233
14039
|
init_summarize_existing_contentful_entities();
|
|
13234
14040
|
init_resolve_session_id();
|
|
@@ -13944,7 +14750,7 @@ var init_user_agent = __esm({
|
|
|
13944
14750
|
// packages/experience-design-system-cli-legacy/src/apply/api-client.ts
|
|
13945
14751
|
import { parseCDFComponents } from "@contentful/experience-design-system-types";
|
|
13946
14752
|
function defaultSleep(delayMs) {
|
|
13947
|
-
return new Promise((
|
|
14753
|
+
return new Promise((resolve21) => setTimeout(resolve21, delayMs));
|
|
13948
14754
|
}
|
|
13949
14755
|
function isTransientStatus(status) {
|
|
13950
14756
|
return status >= 500 && status <= 599;
|
|
@@ -14334,7 +15140,7 @@ ${trimmed}`;
|
|
|
14334
15140
|
const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
|
|
14335
15141
|
const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
|
|
14336
15142
|
const jitter = Math.random() * baseDelay * 0.15;
|
|
14337
|
-
await new Promise((
|
|
15143
|
+
await new Promise((resolve21) => setTimeout(resolve21, baseDelay + jitter));
|
|
14338
15144
|
}
|
|
14339
15145
|
}
|
|
14340
15146
|
throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
|
|
@@ -15144,7 +15950,7 @@ var init_terminal_capabilities = __esm({
|
|
|
15144
15950
|
|
|
15145
15951
|
// packages/experience-design-system-cli-legacy/src/apply/command.ts
|
|
15146
15952
|
import { createElement as createElement2 } from "react";
|
|
15147
|
-
import { readFile as
|
|
15953
|
+
import { readFile as readFile13, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
15148
15954
|
import { join as join16 } from "node:path";
|
|
15149
15955
|
import {
|
|
15150
15956
|
validateCDF,
|
|
@@ -15165,7 +15971,7 @@ function dieWithApiError(error) {
|
|
|
15165
15971
|
async function readJsonFile(flag, p) {
|
|
15166
15972
|
let text;
|
|
15167
15973
|
try {
|
|
15168
|
-
text = await
|
|
15974
|
+
text = await readFile13(p, "utf8");
|
|
15169
15975
|
} catch {
|
|
15170
15976
|
return await die2(`Error: file not found: ${p} (from ${flag})`);
|
|
15171
15977
|
}
|
|
@@ -15219,7 +16025,7 @@ async function readTokensFromPath(flag, p) {
|
|
|
15219
16025
|
for (const file of files.sort()) {
|
|
15220
16026
|
let text;
|
|
15221
16027
|
try {
|
|
15222
|
-
text = await
|
|
16028
|
+
text = await readFile13(file, "utf8");
|
|
15223
16029
|
} catch {
|
|
15224
16030
|
continue;
|
|
15225
16031
|
}
|
|
@@ -15588,11 +16394,11 @@ var init_command2 = __esm({
|
|
|
15588
16394
|
});
|
|
15589
16395
|
|
|
15590
16396
|
// packages/experience-design-system-cli-legacy/src/print/validate/validators/read-json-file.ts
|
|
15591
|
-
import { readFile as
|
|
16397
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
15592
16398
|
async function readJsonFile2(filePath) {
|
|
15593
16399
|
let content;
|
|
15594
16400
|
try {
|
|
15595
|
-
content = await
|
|
16401
|
+
content = await readFile14(filePath, "utf-8");
|
|
15596
16402
|
} catch (err) {
|
|
15597
16403
|
return {
|
|
15598
16404
|
ok: false,
|
|
@@ -16003,7 +16809,7 @@ var init_ValidateView = __esm({
|
|
|
16003
16809
|
// packages/experience-design-system-cli-legacy/src/print/command.ts
|
|
16004
16810
|
import { createElement as createElement3 } from "react";
|
|
16005
16811
|
import { access as access3, mkdir as mkdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
16006
|
-
import { basename as basename5, resolve as
|
|
16812
|
+
import { basename as basename5, resolve as resolve13 } from "node:path";
|
|
16007
16813
|
import { CDF_SCHEMA_URL } from "@contentful/experience-design-system-types";
|
|
16008
16814
|
async function die3(message) {
|
|
16009
16815
|
process.stderr.write(`${message}
|
|
@@ -16070,7 +16876,7 @@ function registerPrintCommand(program) {
|
|
|
16070
16876
|
"--allow-empty",
|
|
16071
16877
|
"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."
|
|
16072
16878
|
).action(async (opts) => {
|
|
16073
|
-
const outPath =
|
|
16879
|
+
const outPath = resolve13(opts.out);
|
|
16074
16880
|
await assertOutIsNotDirectory(outPath);
|
|
16075
16881
|
const sessionId2 = await resolveSession(opts.session, "generate components");
|
|
16076
16882
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16118,7 +16924,7 @@ function registerPrintCommand(program) {
|
|
|
16118
16924
|
`
|
|
16119
16925
|
);
|
|
16120
16926
|
}
|
|
16121
|
-
await mkdir3(
|
|
16927
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16122
16928
|
await writeFile3(outPath, `${JSON.stringify(cdfObj, null, 2)}
|
|
16123
16929
|
`);
|
|
16124
16930
|
process.stdout.write(
|
|
@@ -16127,7 +16933,7 @@ function registerPrintCommand(program) {
|
|
|
16127
16933
|
);
|
|
16128
16934
|
});
|
|
16129
16935
|
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) => {
|
|
16130
|
-
const outPath =
|
|
16936
|
+
const outPath = resolve13(opts.out);
|
|
16131
16937
|
await assertOutIsNotDirectory(outPath);
|
|
16132
16938
|
const sessionId2 = await resolveSession(opts.session, "generate tokens");
|
|
16133
16939
|
await bindAnalyticsSessionId(sessionId2);
|
|
@@ -16142,7 +16948,7 @@ function registerPrintCommand(program) {
|
|
|
16142
16948
|
await die3(`Error: no generated tokens in session '${sessionId2}'. Run generate tokens first.`);
|
|
16143
16949
|
}
|
|
16144
16950
|
const tree = rebuildDTCGTree(result.groups, result.tokens);
|
|
16145
|
-
await mkdir3(
|
|
16951
|
+
await mkdir3(resolve13(outPath, ".."), { recursive: true });
|
|
16146
16952
|
await writeFile3(outPath, `${JSON.stringify(tree, null, 2)}
|
|
16147
16953
|
`);
|
|
16148
16954
|
process.stdout.write(
|
|
@@ -16291,7 +17097,7 @@ function MapTokensView({ result, onExit }) {
|
|
|
16291
17097
|
const timer = setTimeout(onExit, 100);
|
|
16292
17098
|
return () => clearTimeout(timer);
|
|
16293
17099
|
}, [onExit]);
|
|
16294
|
-
const summary = `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
17100
|
+
const summary = result.cached ? "reused from cache" : `${result.applied} mapping${result.applied === 1 ? "" : "s"} applied`;
|
|
16295
17101
|
return /* @__PURE__ */ jsx8(
|
|
16296
17102
|
CommandCompletionView,
|
|
16297
17103
|
{
|
|
@@ -16425,8 +17231,8 @@ var init_resolve_defaults = __esm({
|
|
|
16425
17231
|
|
|
16426
17232
|
// packages/experience-design-system-cli-legacy/src/map-tokens/command.ts
|
|
16427
17233
|
import { createElement as createElement4 } from "react";
|
|
16428
|
-
import { readFile as
|
|
16429
|
-
import { resolve as
|
|
17234
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
17235
|
+
import { resolve as resolve14 } from "node:path";
|
|
16430
17236
|
async function renderResult(result) {
|
|
16431
17237
|
if (process.stdout.isTTY) {
|
|
16432
17238
|
const { waitUntilExit } = renderWithGoodbye(
|
|
@@ -16434,13 +17240,12 @@ async function renderResult(result) {
|
|
|
16434
17240
|
);
|
|
16435
17241
|
await waitUntilExit();
|
|
16436
17242
|
} else {
|
|
16437
|
-
|
|
16438
|
-
|
|
17243
|
+
const summary = result.cached ? "cached" : `${result.applied} mapping(s) applied`;
|
|
17244
|
+
process.stdout.write(`map tokens complete
|
|
16439
17245
|
agent: ${result.agent}
|
|
16440
17246
|
session=${result.sessionId}
|
|
16441
|
-
${
|
|
16442
|
-
`
|
|
16443
|
-
);
|
|
17247
|
+
${summary}
|
|
17248
|
+
`);
|
|
16444
17249
|
await exitWithAnalytics(0);
|
|
16445
17250
|
}
|
|
16446
17251
|
}
|
|
@@ -16462,7 +17267,7 @@ async function runMapTokens(opts) {
|
|
|
16462
17267
|
let mapPromptPath;
|
|
16463
17268
|
if (mapPromptOverride?.kind === "text") mapPromptText = mapPromptOverride.value;
|
|
16464
17269
|
if (mapPromptOverride?.kind === "path") {
|
|
16465
|
-
mapPromptPath =
|
|
17270
|
+
mapPromptPath = resolve14(mapPromptOverride.value);
|
|
16466
17271
|
try {
|
|
16467
17272
|
await resolvePromptOverride(mapPromptOverride);
|
|
16468
17273
|
} catch (error) {
|
|
@@ -16482,7 +17287,7 @@ async function runMapTokens(opts) {
|
|
|
16482
17287
|
const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
|
|
16483
17288
|
const tokenMapDiagnostics = [];
|
|
16484
17289
|
if (opts.tokenMap) {
|
|
16485
|
-
const fileMappings = JSON.parse(await
|
|
17290
|
+
const fileMappings = JSON.parse(await readFile15(opts.tokenMap, "utf8"));
|
|
16486
17291
|
const validMappings = {};
|
|
16487
17292
|
for (const [rawName, path] of Object.entries(fileMappings)) {
|
|
16488
17293
|
if (knownTokenPaths.has(path)) {
|
|
@@ -16560,7 +17365,7 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16560
17365
|
let existingTokensInline;
|
|
16561
17366
|
if (opts.existingEntitiesPath) {
|
|
16562
17367
|
const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
16563
|
-
|
|
17368
|
+
resolve14(opts.existingEntitiesPath)
|
|
16564
17369
|
);
|
|
16565
17370
|
if (existingContentfulEntities) {
|
|
16566
17371
|
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
@@ -16595,10 +17400,30 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
16595
17400
|
skipAgent: "true"
|
|
16596
17401
|
});
|
|
16597
17402
|
updateStep(db, stepId2, "complete", { applied: "0", skipAgent: "true" });
|
|
16598
|
-
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0 });
|
|
17403
|
+
await renderResult({ agent: resultAgent, sessionId: sessionId2, applied: 0, cached: false });
|
|
16599
17404
|
return;
|
|
16600
17405
|
}
|
|
16601
17406
|
const agent = configuredAgent;
|
|
17407
|
+
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
17408
|
+
const promptHash = await hashPromptForSkill(
|
|
17409
|
+
"map-tokens",
|
|
17410
|
+
agent,
|
|
17411
|
+
model,
|
|
17412
|
+
void 0,
|
|
17413
|
+
existingTokensInline ? [hashContent(existingTokensInline)] : [],
|
|
17414
|
+
mapPromptText
|
|
17415
|
+
);
|
|
17416
|
+
const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
|
|
17417
|
+
if (!noCache) {
|
|
17418
|
+
const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
|
|
17419
|
+
if (cached) {
|
|
17420
|
+
const appliedFromCache = copyMapTokensFromCache(db, cached.sourceSessionId, sessionId2);
|
|
17421
|
+
const stepId2 = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
|
|
17422
|
+
updateStep(db, stepId2, "complete", { cached: "true", applied: String(appliedFromCache) });
|
|
17423
|
+
await renderResult({ agent, sessionId: sessionId2, applied: appliedFromCache, cached: true });
|
|
17424
|
+
return;
|
|
17425
|
+
}
|
|
17426
|
+
}
|
|
16602
17427
|
const binary = resolveAgentBinary(agent);
|
|
16603
17428
|
if (!await assertBinaryInPath(binary)) {
|
|
16604
17429
|
die(
|
|
@@ -16618,20 +17443,23 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
16618
17443
|
}
|
|
16619
17444
|
const { calls, warnings: parseWarnings } = parseMapTokenPropToolCallLines(result.stdout);
|
|
16620
17445
|
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, calls, parseWarnings);
|
|
17446
|
+
if (!noCache) {
|
|
17447
|
+
storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId2, false, promptHash);
|
|
17448
|
+
}
|
|
16621
17449
|
updateStep(db, stepId, "complete", { applied: String(applied), warnings: String(warnings.length) });
|
|
16622
17450
|
if (warnings.length > 0) {
|
|
16623
17451
|
process.stderr.write(`Warnings:
|
|
16624
17452
|
${warnings.map((w) => ` ${w}`).join("\n")}
|
|
16625
17453
|
`);
|
|
16626
17454
|
}
|
|
16627
|
-
await renderResult({ agent, sessionId: sessionId2, applied });
|
|
17455
|
+
await renderResult({ agent, sessionId: sessionId2, applied, cached: false });
|
|
16628
17456
|
} finally {
|
|
16629
17457
|
db.close();
|
|
16630
17458
|
}
|
|
16631
17459
|
}
|
|
16632
17460
|
function registerMapTokensCommand(program) {
|
|
16633
17461
|
const map = program.command("map", { hidden: true }).description("Suggest token restrictions for generated design-token props");
|
|
16634
|
-
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(
|
|
17462
|
+
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(
|
|
16635
17463
|
"--prompt <stage=value>",
|
|
16636
17464
|
"Override a stage prompt (repeatable). Used here for the map-tokens stage.",
|
|
16637
17465
|
(v, acc) => [...acc, v],
|
|
@@ -16651,6 +17479,7 @@ var init_command4 = __esm({
|
|
|
16651
17479
|
init_render_with_goodbye();
|
|
16652
17480
|
init_src();
|
|
16653
17481
|
init_db();
|
|
17482
|
+
init_cache_keys();
|
|
16654
17483
|
init_read_existing_contentful_entities_from_session();
|
|
16655
17484
|
init_summarize_existing_contentful_entities();
|
|
16656
17485
|
init_command3();
|
|
@@ -16667,7 +17496,7 @@ var init_command4 = __esm({
|
|
|
16667
17496
|
});
|
|
16668
17497
|
|
|
16669
17498
|
// packages/experience-design-system-cli-legacy/src/import/path-utils.ts
|
|
16670
|
-
import { resolve as
|
|
17499
|
+
import { resolve as resolve15 } from "node:path";
|
|
16671
17500
|
import { homedir as homedir5 } from "node:os";
|
|
16672
17501
|
function expandTilde(input) {
|
|
16673
17502
|
if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
|
|
@@ -16681,7 +17510,7 @@ function normalizePath(input) {
|
|
|
16681
17510
|
p = p.slice(1, -1);
|
|
16682
17511
|
}
|
|
16683
17512
|
p = expandTilde(p);
|
|
16684
|
-
return
|
|
17513
|
+
return resolve15(p);
|
|
16685
17514
|
}
|
|
16686
17515
|
var init_path_utils = __esm({
|
|
16687
17516
|
"packages/experience-design-system-cli-legacy/src/import/path-utils.ts"() {
|
|
@@ -16906,7 +17735,7 @@ var init_save_path_resolver = __esm({
|
|
|
16906
17735
|
});
|
|
16907
17736
|
|
|
16908
17737
|
// packages/experience-design-system-cli-legacy/src/runs/store.ts
|
|
16909
|
-
import { readFile as
|
|
17738
|
+
import { readFile as readFile16, writeFile as writeFile4, mkdir as mkdir4, rename } from "node:fs/promises";
|
|
16910
17739
|
import { join as join20 } from "node:path";
|
|
16911
17740
|
import { homedir as homedir6 } from "node:os";
|
|
16912
17741
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -16946,7 +17775,7 @@ function migrateRecord(rec) {
|
|
|
16946
17775
|
}
|
|
16947
17776
|
async function readFileMaybe() {
|
|
16948
17777
|
try {
|
|
16949
|
-
const raw = await
|
|
17778
|
+
const raw = await readFile16(RUNS_PATH, "utf8");
|
|
16950
17779
|
const parsed = JSON.parse(raw);
|
|
16951
17780
|
if (!READABLE_VERSIONS.has(parsed.version)) {
|
|
16952
17781
|
throw new Error(
|
|
@@ -17010,15 +17839,15 @@ var init_store = __esm({
|
|
|
17010
17839
|
});
|
|
17011
17840
|
|
|
17012
17841
|
// packages/experience-design-system-cli-legacy/src/runs/fingerprint.ts
|
|
17013
|
-
import { createHash as
|
|
17014
|
-
import { readFile as
|
|
17015
|
-
import { resolve as
|
|
17842
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
17843
|
+
import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
|
|
17844
|
+
import { resolve as resolve16 } from "node:path";
|
|
17016
17845
|
function rowField(row, key) {
|
|
17017
17846
|
const v = row[key];
|
|
17018
17847
|
return typeof v === "string" ? v : null;
|
|
17019
17848
|
}
|
|
17020
17849
|
function sha256Hex(buf) {
|
|
17021
|
-
return
|
|
17850
|
+
return createHash6("sha256").update(buf).digest("hex");
|
|
17022
17851
|
}
|
|
17023
17852
|
async function buildSourceFingerprint(opts) {
|
|
17024
17853
|
const rows = opts.db.prepare("SELECT name, source_path FROM raw_components WHERE session_id = ?").all(opts.extractSessionId);
|
|
@@ -17028,7 +17857,7 @@ async function buildSourceFingerprint(opts) {
|
|
|
17028
17857
|
const sourcePath = rowField(row, "source_path");
|
|
17029
17858
|
const name = rowField(row, "name");
|
|
17030
17859
|
if (!sourcePath) continue;
|
|
17031
|
-
const abs =
|
|
17860
|
+
const abs = resolve16(sourcePath);
|
|
17032
17861
|
if (seen.has(abs)) continue;
|
|
17033
17862
|
seen.add(abs);
|
|
17034
17863
|
try {
|
|
@@ -17043,10 +17872,10 @@ async function buildSourceFingerprint(opts) {
|
|
|
17043
17872
|
let rawTokensMtime = null;
|
|
17044
17873
|
let rawTokensContentHash = null;
|
|
17045
17874
|
if (opts.rawTokensPath) {
|
|
17046
|
-
const abs =
|
|
17875
|
+
const abs = resolve16(opts.rawTokensPath);
|
|
17047
17876
|
rawTokensPath = abs;
|
|
17048
17877
|
try {
|
|
17049
|
-
const [st, buf] = await Promise.all([stat4(abs),
|
|
17878
|
+
const [st, buf] = await Promise.all([stat4(abs), readFile17(abs)]);
|
|
17050
17879
|
rawTokensMtime = st.mtime.toISOString();
|
|
17051
17880
|
rawTokensContentHash = sha256Hex(buf);
|
|
17052
17881
|
} catch {
|
|
@@ -18801,11 +19630,11 @@ var init_slot_graph = __esm({
|
|
|
18801
19630
|
});
|
|
18802
19631
|
|
|
18803
19632
|
// packages/experience-design-system-cli-legacy/src/analyze/select/parser.ts
|
|
18804
|
-
import { createHash as
|
|
19633
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
18805
19634
|
import { access as access5 } from "node:fs/promises";
|
|
18806
|
-
import { isAbsolute, relative, resolve as
|
|
19635
|
+
import { isAbsolute, relative, resolve as resolve17 } from "node:path";
|
|
18807
19636
|
function createComponentId(name, resolvedSourcePath) {
|
|
18808
|
-
const sourceHash =
|
|
19637
|
+
const sourceHash = createHash7("sha256").update(`${name}:${resolvedSourcePath}`).digest("hex").slice(0, 12);
|
|
18809
19638
|
return `${name}-${sourceHash}`;
|
|
18810
19639
|
}
|
|
18811
19640
|
async function resolveComponentSourcePath(source, reviewRoot) {
|
|
@@ -18817,7 +19646,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18817
19646
|
throw new Error(`Unable to access component source at ${source}`);
|
|
18818
19647
|
}
|
|
18819
19648
|
}
|
|
18820
|
-
const candidate =
|
|
19649
|
+
const candidate = resolve17(reviewRoot, source);
|
|
18821
19650
|
const relativeToRoot = relative(reviewRoot, candidate);
|
|
18822
19651
|
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || isAbsolute(relativeToRoot)) {
|
|
18823
19652
|
throw new Error(
|
|
@@ -18832,7 +19661,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
|
|
|
18832
19661
|
}
|
|
18833
19662
|
}
|
|
18834
19663
|
async function loadReviewInput(components, options = {}) {
|
|
18835
|
-
const reviewRoot =
|
|
19664
|
+
const reviewRoot = resolve17(options.reviewRoot ?? process.cwd());
|
|
18836
19665
|
const records = await Promise.all(
|
|
18837
19666
|
components.map(async (component) => {
|
|
18838
19667
|
let resolvedSourcePath;
|
|
@@ -18863,7 +19692,7 @@ var init_parser = __esm({
|
|
|
18863
19692
|
});
|
|
18864
19693
|
|
|
18865
19694
|
// packages/experience-design-system-cli-legacy/src/analyze/select/command.ts
|
|
18866
|
-
import { access as access6, readFile as
|
|
19695
|
+
import { access as access6, readFile as readFile18 } from "node:fs/promises";
|
|
18867
19696
|
async function loadAndValidateForReview(sessionId2, projectRoot) {
|
|
18868
19697
|
const db = openPipelineDb();
|
|
18869
19698
|
let rawComponents;
|
|
@@ -18881,7 +19710,7 @@ async function patchReviewStateWithValidationErrors(sessionId2, errors, opts = {
|
|
|
18881
19710
|
let snapshot;
|
|
18882
19711
|
try {
|
|
18883
19712
|
await access6(paths.statePath);
|
|
18884
|
-
snapshot = JSON.parse(await
|
|
19713
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18885
19714
|
} catch {
|
|
18886
19715
|
snapshot = await loadAndValidateForReview(sessionId2, void 0);
|
|
18887
19716
|
snapshot = await ensureRefineSession(sessionId2, artifactsRoot, snapshot);
|
|
@@ -18932,7 +19761,7 @@ async function rejectComponentsByName(sessionId2, names, opts = {}) {
|
|
|
18932
19761
|
const nameSet = new Set(names);
|
|
18933
19762
|
let snapshot;
|
|
18934
19763
|
try {
|
|
18935
|
-
snapshot = JSON.parse(await
|
|
19764
|
+
snapshot = JSON.parse(await readFile18(paths.statePath, "utf8"));
|
|
18936
19765
|
} catch {
|
|
18937
19766
|
return;
|
|
18938
19767
|
}
|
|
@@ -19031,9 +19860,9 @@ function spawnGenerateChild(opts) {
|
|
|
19031
19860
|
stderr += chunk;
|
|
19032
19861
|
opts.onStderr?.(chunk);
|
|
19033
19862
|
});
|
|
19034
|
-
const donePromise = new Promise((
|
|
19863
|
+
const donePromise = new Promise((resolve21) => {
|
|
19035
19864
|
child.on("close", (code, signal) => {
|
|
19036
|
-
|
|
19865
|
+
resolve21({
|
|
19037
19866
|
exitCode: code ?? 0,
|
|
19038
19867
|
signal: signal ?? null,
|
|
19039
19868
|
stdout,
|
|
@@ -19041,7 +19870,7 @@ function spawnGenerateChild(opts) {
|
|
|
19041
19870
|
});
|
|
19042
19871
|
});
|
|
19043
19872
|
child.on("error", (err) => {
|
|
19044
|
-
|
|
19873
|
+
resolve21({
|
|
19045
19874
|
exitCode: 1,
|
|
19046
19875
|
signal: null,
|
|
19047
19876
|
stdout,
|
|
@@ -27179,6 +28008,9 @@ function shouldGenerateAfterCredentialsValidated(opts) {
|
|
|
27179
28008
|
function shouldSkipFinalReviewAfterCredentials(state) {
|
|
27180
28009
|
return state.finalReviewPassed && state.generateSessionId != null;
|
|
27181
28010
|
}
|
|
28011
|
+
function resolveNoCacheForGenerate(opts) {
|
|
28012
|
+
return opts.cliNoCache;
|
|
28013
|
+
}
|
|
27182
28014
|
function shouldBypassPreview(state) {
|
|
27183
28015
|
return state.credentialsSkipped === true;
|
|
27184
28016
|
}
|
|
@@ -27205,43 +28037,70 @@ var init_wizard_state_transitions = __esm({
|
|
|
27205
28037
|
async function runSelectionAgent(options) {
|
|
27206
28038
|
const db = openPipelineDb();
|
|
27207
28039
|
let components;
|
|
28040
|
+
const cachedDecisions = /* @__PURE__ */ new Map();
|
|
28041
|
+
const cliVersion2 = await getCliCacheVersion();
|
|
28042
|
+
const promptHash = await hashPromptForSkill(
|
|
28043
|
+
"select",
|
|
28044
|
+
options.agent,
|
|
28045
|
+
options.model,
|
|
28046
|
+
options.promptPath,
|
|
28047
|
+
[SELECT_PAYLOAD_FORMAT],
|
|
28048
|
+
options.promptText
|
|
28049
|
+
);
|
|
27208
28050
|
try {
|
|
27209
28051
|
components = loadRawComponents(db, options.sessionId);
|
|
28052
|
+
if (!options.noCache) {
|
|
28053
|
+
for (const component of components) {
|
|
28054
|
+
const componentHash = hashComponentShape(component);
|
|
28055
|
+
const cached = lookupSelectCache(db, componentHash, promptHash, cliVersion2);
|
|
28056
|
+
if (cached) {
|
|
28057
|
+
cachedDecisions.set(component.name, {
|
|
28058
|
+
decision: cached.decision,
|
|
28059
|
+
reason: cached.reason
|
|
28060
|
+
});
|
|
28061
|
+
}
|
|
28062
|
+
}
|
|
28063
|
+
}
|
|
27210
28064
|
} finally {
|
|
27211
28065
|
db.close();
|
|
27212
28066
|
}
|
|
27213
28067
|
if (components.length === 0) return;
|
|
27214
|
-
const
|
|
27215
|
-
|
|
27216
|
-
|
|
27217
|
-
|
|
27218
|
-
|
|
27219
|
-
|
|
27220
|
-
|
|
27221
|
-
|
|
27222
|
-
|
|
27223
|
-
|
|
27224
|
-
|
|
27225
|
-
|
|
27226
|
-
|
|
27227
|
-
|
|
27228
|
-
|
|
27229
|
-
|
|
27230
|
-
|
|
27231
|
-
|
|
27232
|
-
|
|
27233
|
-
|
|
27234
|
-
|
|
27235
|
-
|
|
27236
|
-
|
|
27237
|
-
|
|
27238
|
-
|
|
27239
|
-
|
|
27240
|
-
|
|
27241
|
-
|
|
27242
|
-
|
|
28068
|
+
const componentsToRun = components.filter((component) => !cachedDecisions.has(component.name));
|
|
28069
|
+
let calls = [];
|
|
28070
|
+
if (componentsToRun.length > 0) {
|
|
28071
|
+
const invoker2 = createLocalCliAgentInvoker({
|
|
28072
|
+
onDebugEvent: (name, payload) => getDebugLogger().event("agent", name, payload)
|
|
28073
|
+
});
|
|
28074
|
+
const selectBuckets = bucketComponentsProps(componentsToRun);
|
|
28075
|
+
for (const assignment of selectBuckets) {
|
|
28076
|
+
getDebugLogger().event("analyze", "prop-buckets.select", { ...assignment });
|
|
28077
|
+
}
|
|
28078
|
+
const prompt = await buildPrompt({
|
|
28079
|
+
skill: "select",
|
|
28080
|
+
mode: "autonomous",
|
|
28081
|
+
rawComponentsInline: JSON.stringify(
|
|
28082
|
+
componentsToRun.map((component) => ({ ...component, props: component.props.map(stripPropProvenance) })),
|
|
28083
|
+
null,
|
|
28084
|
+
2
|
|
28085
|
+
),
|
|
28086
|
+
propBucketsInline: JSON.stringify(selectBuckets),
|
|
28087
|
+
outDir: process.cwd(),
|
|
28088
|
+
...options.promptText !== void 0 ? { skillContentOverride: options.promptText } : {},
|
|
28089
|
+
...options.promptText === void 0 && options.promptPath ? { skillPathOverride: options.promptPath } : {}
|
|
28090
|
+
});
|
|
28091
|
+
const { result } = await invokeAgentWithOutput(
|
|
28092
|
+
invoker2,
|
|
28093
|
+
{ agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
|
|
28094
|
+
false
|
|
28095
|
+
);
|
|
28096
|
+
if (result.timedOut) throw new Error("selection agent timed out");
|
|
28097
|
+
if (result.exitCode !== 0) throw new Error(`selection agent exited with code ${result.exitCode}`);
|
|
28098
|
+
const parsed = parseSelectToolCallLines(result.stdout);
|
|
28099
|
+
for (const warning of parsed.warnings) process.stderr.write(`Warning: selection agent: ${warning}
|
|
27243
28100
|
`);
|
|
27244
|
-
|
|
28101
|
+
calls = parsed.calls;
|
|
28102
|
+
}
|
|
28103
|
+
const byName = new Map(calls.map((call) => [call.name, call]));
|
|
27245
28104
|
const writeDb = openPipelineDb();
|
|
27246
28105
|
try {
|
|
27247
28106
|
writeDb.exec("BEGIN");
|
|
@@ -27249,15 +28108,27 @@ async function runSelectionAgent(options) {
|
|
|
27249
28108
|
`UPDATE raw_components SET status = ?, reject_reason = ? WHERE session_id = ? AND component_id = ?`
|
|
27250
28109
|
);
|
|
27251
28110
|
for (const component of components) {
|
|
28111
|
+
const cached = cachedDecisions.get(component.name);
|
|
27252
28112
|
const call = byName.get(component.name);
|
|
27253
|
-
if (!call) continue;
|
|
27254
|
-
const rejected = call.tool === "reject_component";
|
|
28113
|
+
if (!cached && !call) continue;
|
|
28114
|
+
const rejected = cached ? cached.decision === "rejected" : call.tool === "reject_component";
|
|
28115
|
+
const reason = cached ? cached.reason : call.reason ?? null;
|
|
27255
28116
|
update.run(
|
|
27256
28117
|
rejected ? "rejected" : "accepted",
|
|
27257
|
-
rejected ?
|
|
28118
|
+
rejected ? reason : null,
|
|
27258
28119
|
options.sessionId,
|
|
27259
28120
|
component.component_id
|
|
27260
28121
|
);
|
|
28122
|
+
if (!cached) {
|
|
28123
|
+
storeSelectCache(
|
|
28124
|
+
writeDb,
|
|
28125
|
+
hashComponentShape(component),
|
|
28126
|
+
promptHash,
|
|
28127
|
+
cliVersion2,
|
|
28128
|
+
rejected ? "rejected" : "accepted",
|
|
28129
|
+
rejected ? reason : null
|
|
28130
|
+
);
|
|
28131
|
+
}
|
|
27261
28132
|
}
|
|
27262
28133
|
writeDb.exec("COMMIT");
|
|
27263
28134
|
} catch (error) {
|
|
@@ -27267,7 +28138,7 @@ async function runSelectionAgent(options) {
|
|
|
27267
28138
|
writeDb.close();
|
|
27268
28139
|
}
|
|
27269
28140
|
}
|
|
27270
|
-
var DEFAULT_TIMEOUT_MS4;
|
|
28141
|
+
var SELECT_PAYLOAD_FORMAT, DEFAULT_TIMEOUT_MS4;
|
|
27271
28142
|
var init_run_selection_agent = __esm({
|
|
27272
28143
|
"packages/experience-design-system-cli-legacy/src/import/tui/run-selection-agent.ts"() {
|
|
27273
28144
|
"use strict";
|
|
@@ -27276,6 +28147,8 @@ var init_run_selection_agent = __esm({
|
|
|
27276
28147
|
init_debug_logger();
|
|
27277
28148
|
init_agent_output();
|
|
27278
28149
|
init_db();
|
|
28150
|
+
init_cache_keys();
|
|
28151
|
+
SELECT_PAYLOAD_FORMAT = "prop-buckets-v1";
|
|
27279
28152
|
DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
|
|
27280
28153
|
}
|
|
27281
28154
|
});
|
|
@@ -27294,7 +28167,7 @@ __export(WizardApp_exports, {
|
|
|
27294
28167
|
});
|
|
27295
28168
|
import { useEffect as useEffect15, useRef as useRef10, useState as useState23 } from "react";
|
|
27296
28169
|
import { Box as Box42, Text as Text46 } from "ink";
|
|
27297
|
-
import { join as join23, resolve as
|
|
28170
|
+
import { join as join23, resolve as resolve18 } from "node:path";
|
|
27298
28171
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27299
28172
|
import { access as access7, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
27300
28173
|
import { tmpdir } from "node:os";
|
|
@@ -27307,21 +28180,28 @@ function buildGenerateComponentsArgs(opts) {
|
|
|
27307
28180
|
if (opts.tokensPath) args.push("--tokens", opts.tokensPath);
|
|
27308
28181
|
if (opts.model) args.push("--model", opts.model);
|
|
27309
28182
|
if (opts.bedrock) args.push("--bedrock");
|
|
28183
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27310
28184
|
if (opts.generatePromptPath) args.push("--generate-prompt-path", opts.generatePromptPath);
|
|
27311
28185
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27312
28186
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
28187
|
+
if (opts.restoreCache) args.push("--restore-cache");
|
|
28188
|
+
if (opts.cachedComponents && opts.cachedComponents.length > 0) {
|
|
28189
|
+
args.push("--cached-components", JSON.stringify(opts.cachedComponents));
|
|
28190
|
+
}
|
|
27313
28191
|
return args;
|
|
27314
28192
|
}
|
|
27315
28193
|
function buildGenerateTokensArgs(opts) {
|
|
27316
28194
|
const args = [findCliPath(), "__generate", "tokens", "--agent", opts.agent, "--raw-tokens", opts.rawTokensPath];
|
|
27317
28195
|
if (opts.model) args.push("--model", opts.model);
|
|
27318
28196
|
if (opts.bedrock) args.push("--bedrock");
|
|
28197
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27319
28198
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27320
28199
|
return args;
|
|
27321
28200
|
}
|
|
27322
28201
|
function buildMapTokensArgs(opts) {
|
|
27323
28202
|
const args = ["map", "tokens", "--session", opts.sessionId, "--agent", opts.agent];
|
|
27324
28203
|
if (opts.model) args.push("--model", opts.model);
|
|
28204
|
+
if (opts.noCache) args.push("--no-cache");
|
|
27325
28205
|
if (opts.skipAgent) args.push("--skip-agent");
|
|
27326
28206
|
for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
|
|
27327
28207
|
if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
|
|
@@ -27413,6 +28293,7 @@ function WizardApp({
|
|
|
27413
28293
|
initialProjectPath,
|
|
27414
28294
|
host,
|
|
27415
28295
|
promptOverrides,
|
|
28296
|
+
noCache = false,
|
|
27416
28297
|
livePreview = true,
|
|
27417
28298
|
generatePromptPath,
|
|
27418
28299
|
skipMapTokens = false,
|
|
@@ -27437,6 +28318,7 @@ function WizardApp({
|
|
|
27437
28318
|
});
|
|
27438
28319
|
const allowEmptyDeleteAllRef = useRef10(false);
|
|
27439
28320
|
const generateChildRef = useRef10(null);
|
|
28321
|
+
const generationCachePreflightRef = useRef10(null);
|
|
27440
28322
|
const selectionToReviewStartedAtRef = useRef10(null);
|
|
27441
28323
|
const credentialsValidationIdRef = useRef10(0);
|
|
27442
28324
|
const pendingCredentialValidationRef = useRef10(null);
|
|
@@ -27451,8 +28333,9 @@ function WizardApp({
|
|
|
27451
28333
|
const existingEntitiesPromiseRef = useRef10(null);
|
|
27452
28334
|
const generatePromiseRef = useRef10(null);
|
|
27453
28335
|
const rawTokensEntryReady = !!initialRawTokensPath;
|
|
28336
|
+
const effectiveNoCache = resolveNoCacheForGenerate({ cliNoCache: noCache });
|
|
27454
28337
|
const initialStepResolved = rawTokensEntryReady ? initialProjectPath ? "path-validation" : "credentials" : initialProjectPath ? "token-input" : "welcome";
|
|
27455
|
-
const initialOutDir = initialProjectPath ? join23(
|
|
28338
|
+
const initialOutDir = initialProjectPath ? join23(resolve18(initialProjectPath), ".contentful") : "";
|
|
27456
28339
|
const [state, setState] = useState23({
|
|
27457
28340
|
step: initialStepResolved,
|
|
27458
28341
|
agent: initialAgent ?? "claude",
|
|
@@ -27628,13 +28511,14 @@ If you are using AWS Bedrock, run:
|
|
|
27628
28511
|
if (!deferStep) update({ step: nextStep });
|
|
27629
28512
|
return true;
|
|
27630
28513
|
};
|
|
27631
|
-
const runGenerateTokens = async (rawTokensPath, outDir) => {
|
|
28514
|
+
const runGenerateTokens = async (rawTokensPath, outDir, forceRegenerate = false) => {
|
|
27632
28515
|
update({ tokenGenerationStatus: "running" });
|
|
27633
28516
|
const tokenArgs = buildGenerateTokensArgs({
|
|
27634
28517
|
rawTokensPath,
|
|
27635
28518
|
agent: state.agent,
|
|
27636
28519
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27637
28520
|
...state.bedrock ? { bedrock: true } : {},
|
|
28521
|
+
noCache: effectiveNoCache || forceRegenerate,
|
|
27638
28522
|
promptOverrides
|
|
27639
28523
|
});
|
|
27640
28524
|
const result = await runSpawnedCli(tokenArgs);
|
|
@@ -27683,6 +28567,7 @@ If you are using AWS Bedrock, run:
|
|
|
27683
28567
|
const timer = startWizardTimer("token-mapping", {
|
|
27684
28568
|
sessionId: sessionId2,
|
|
27685
28569
|
silent,
|
|
28570
|
+
noCache: effectiveNoCache,
|
|
27686
28571
|
skipAgent: skipMapTokens
|
|
27687
28572
|
});
|
|
27688
28573
|
let mappablePropCount = 0;
|
|
@@ -27691,7 +28576,7 @@ If you are using AWS Bedrock, run:
|
|
|
27691
28576
|
const db = openPipelineDb();
|
|
27692
28577
|
try {
|
|
27693
28578
|
if (state.tokenSessionId && state.tokenSessionId !== sessionId2) {
|
|
27694
|
-
|
|
28579
|
+
copyTokensFromCache(db, state.tokenSessionId, sessionId2);
|
|
27695
28580
|
} else if (!state.tokenSessionId && state.tokensPath) {
|
|
27696
28581
|
const tokens = await readTokensFromPath("tokens", state.tokensPath);
|
|
27697
28582
|
storeDtcgTokens(db, sessionId2, [], tokens);
|
|
@@ -27731,6 +28616,7 @@ If you are using AWS Bedrock, run:
|
|
|
27731
28616
|
sessionId: sessionId2,
|
|
27732
28617
|
agent: state.agent,
|
|
27733
28618
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28619
|
+
noCache: effectiveNoCache,
|
|
27734
28620
|
skipAgent: skipMapTokens,
|
|
27735
28621
|
promptOverrides,
|
|
27736
28622
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
|
|
@@ -27810,7 +28696,7 @@ If you are using AWS Bedrock, run:
|
|
|
27810
28696
|
return promise;
|
|
27811
28697
|
};
|
|
27812
28698
|
const runExtract = async (projectPath, showProgress = true) => {
|
|
27813
|
-
const outDir = join23(
|
|
28699
|
+
const outDir = join23(resolve18(projectPath), ".contentful");
|
|
27814
28700
|
const existingEntitiesExpected = !state.credentialsSkipped && Boolean(state.spaceId && state.environmentId && state.cmaToken && projectPath);
|
|
27815
28701
|
update({
|
|
27816
28702
|
...showProgress ? { step: "extracting" } : {},
|
|
@@ -27825,6 +28711,7 @@ If you are using AWS Bedrock, run:
|
|
|
27825
28711
|
});
|
|
27826
28712
|
const existingEntitiesPromise = startExistingEntitiesFetch(projectPath, outDir);
|
|
27827
28713
|
const extractArgs = [findCliPath(), "__extract", "--project", projectPath];
|
|
28714
|
+
if (effectiveNoCache) extractArgs.push("--no-cache");
|
|
27828
28715
|
let selectionPromptText;
|
|
27829
28716
|
let selectionPromptPath;
|
|
27830
28717
|
try {
|
|
@@ -27833,7 +28720,7 @@ If you are using AWS Bedrock, run:
|
|
|
27833
28720
|
const selectOverride = overrides.get("select");
|
|
27834
28721
|
if (selectOverride?.kind === "text") selectionPromptText = selectOverride.value;
|
|
27835
28722
|
if (selectOverride?.kind === "path") {
|
|
27836
|
-
selectionPromptPath =
|
|
28723
|
+
selectionPromptPath = resolve18(selectOverride.value);
|
|
27837
28724
|
await resolvePromptOverride(selectOverride);
|
|
27838
28725
|
}
|
|
27839
28726
|
} catch (error) {
|
|
@@ -27857,7 +28744,8 @@ If you are using AWS Bedrock, run:
|
|
|
27857
28744
|
agent: state.agent,
|
|
27858
28745
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
27859
28746
|
...selectionPromptText !== void 0 ? { promptText: selectionPromptText } : {},
|
|
27860
|
-
...selectionPromptPath ? { promptPath: selectionPromptPath } : {}
|
|
28747
|
+
...selectionPromptPath ? { promptPath: selectionPromptPath } : {},
|
|
28748
|
+
noCache: effectiveNoCache
|
|
27861
28749
|
});
|
|
27862
28750
|
})().catch((error) => {
|
|
27863
28751
|
selectionError = error;
|
|
@@ -28002,17 +28890,136 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28002
28890
|
generateProgress: null
|
|
28003
28891
|
}));
|
|
28004
28892
|
};
|
|
28005
|
-
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2) => ({
|
|
28893
|
+
const buildGenerateOptions = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => ({
|
|
28006
28894
|
sessionId: extractSessionId,
|
|
28007
28895
|
tokensPath,
|
|
28008
28896
|
agent: state.agent,
|
|
28009
28897
|
...state.agentModel ? { model: state.agentModel } : {},
|
|
28010
28898
|
...state.bedrock ? { bedrock: true } : {},
|
|
28899
|
+
noCache: effectiveNoCache,
|
|
28011
28900
|
...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {},
|
|
28012
28901
|
...generatePromptPath2 ? { generatePromptPath: generatePromptPath2 } : {},
|
|
28013
|
-
promptOverrides
|
|
28902
|
+
promptOverrides,
|
|
28903
|
+
...cachedComponents && cachedComponents.length > 0 ? { cachedComponents } : {}
|
|
28014
28904
|
});
|
|
28015
|
-
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2));
|
|
28905
|
+
const buildGenerateArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateProcessArgs(buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents));
|
|
28906
|
+
const buildGenerateCliArgs = (extractSessionId, tokensPath, generatePromptPath2, cachedComponents) => buildGenerateComponentsArgs(
|
|
28907
|
+
buildGenerateOptions(extractSessionId, tokensPath, generatePromptPath2, cachedComponents)
|
|
28908
|
+
);
|
|
28909
|
+
const checkGenerateCache = async (extractSessionId, tokensPath) => {
|
|
28910
|
+
const timer = startWizardTimer("generation-cache-status", {
|
|
28911
|
+
sessionId: extractSessionId,
|
|
28912
|
+
noCache: effectiveNoCache
|
|
28913
|
+
});
|
|
28914
|
+
if (effectiveNoCache) {
|
|
28915
|
+
finishWizardTimer("generation-cache-status", timer, { status: "skipped" });
|
|
28916
|
+
return false;
|
|
28917
|
+
}
|
|
28918
|
+
const result = await runCli([...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"]);
|
|
28919
|
+
const hit = result.exitCode === 0 && /^cache-status=hit$/m.test(result.stdout);
|
|
28920
|
+
finishWizardTimer("generation-cache-status", timer, {
|
|
28921
|
+
status: hit ? "hit" : "miss",
|
|
28922
|
+
exitCode: result.exitCode,
|
|
28923
|
+
...result.exitCode !== 0 ? { stderrTail: result.stderr.trim().slice(-500) } : {}
|
|
28924
|
+
});
|
|
28925
|
+
return hit;
|
|
28926
|
+
};
|
|
28927
|
+
const checkGenerateCacheComponents = async (extractSessionId, tokensPath, restoreCache = false) => {
|
|
28928
|
+
const timer = startWizardTimer("generation-cache-components", {
|
|
28929
|
+
sessionId: extractSessionId,
|
|
28930
|
+
restoreCache,
|
|
28931
|
+
noCache: effectiveNoCache
|
|
28932
|
+
});
|
|
28933
|
+
if (effectiveNoCache) {
|
|
28934
|
+
finishWizardTimer("generation-cache-components", timer, { status: "skipped" });
|
|
28935
|
+
return /* @__PURE__ */ new Set();
|
|
28936
|
+
}
|
|
28937
|
+
const args = [...buildGenerateCliArgs(extractSessionId, tokensPath), "--cache-status"];
|
|
28938
|
+
if (restoreCache) args.push("--restore-cache");
|
|
28939
|
+
const result = await runCli(args);
|
|
28940
|
+
if (result.exitCode !== 0) {
|
|
28941
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28942
|
+
status: "error",
|
|
28943
|
+
exitCode: result.exitCode,
|
|
28944
|
+
stderrTail: result.stderr.trim().slice(-500)
|
|
28945
|
+
});
|
|
28946
|
+
return /* @__PURE__ */ new Set();
|
|
28947
|
+
}
|
|
28948
|
+
const line = /^cache-components=(.+)$/m.exec(result.stdout)?.[1];
|
|
28949
|
+
if (!line) {
|
|
28950
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28951
|
+
status: "missing-output",
|
|
28952
|
+
exitCode: result.exitCode,
|
|
28953
|
+
cachedCount: 0
|
|
28954
|
+
});
|
|
28955
|
+
return /* @__PURE__ */ new Set();
|
|
28956
|
+
}
|
|
28957
|
+
try {
|
|
28958
|
+
const names = JSON.parse(line);
|
|
28959
|
+
const cachedNames = new Set(
|
|
28960
|
+
Array.isArray(names) ? names.filter((name) => typeof name === "string") : []
|
|
28961
|
+
);
|
|
28962
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28963
|
+
status: "complete",
|
|
28964
|
+
exitCode: result.exitCode,
|
|
28965
|
+
cachedCount: cachedNames.size
|
|
28966
|
+
});
|
|
28967
|
+
return cachedNames;
|
|
28968
|
+
} catch {
|
|
28969
|
+
finishWizardTimer("generation-cache-components", timer, {
|
|
28970
|
+
status: "invalid-output",
|
|
28971
|
+
exitCode: result.exitCode,
|
|
28972
|
+
cachedCount: 0
|
|
28973
|
+
});
|
|
28974
|
+
return /* @__PURE__ */ new Set();
|
|
28975
|
+
}
|
|
28976
|
+
};
|
|
28977
|
+
useEffect15(() => {
|
|
28978
|
+
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) {
|
|
28979
|
+
return;
|
|
28980
|
+
}
|
|
28981
|
+
const sessionId2 = state.extractSessionId;
|
|
28982
|
+
if (generationCachePreflightRef.current?.sessionId === sessionId2) return;
|
|
28983
|
+
const timer = startWizardTimer("generation-cache-preflight", { sessionId: sessionId2 });
|
|
28984
|
+
const db = openPipelineDb();
|
|
28985
|
+
let generatedNames = null;
|
|
28986
|
+
try {
|
|
28987
|
+
const rows = db.prepare("SELECT name, status FROM raw_components WHERE session_id = ?").all(sessionId2);
|
|
28988
|
+
if (rows.length > 0 && rows.every((row) => row.status === "generated")) {
|
|
28989
|
+
generatedNames = new Set(rows.map((row) => row.name));
|
|
28990
|
+
}
|
|
28991
|
+
} finally {
|
|
28992
|
+
db.close();
|
|
28993
|
+
}
|
|
28994
|
+
if (generatedNames) {
|
|
28995
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: Promise.resolve(generatedNames) };
|
|
28996
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
28997
|
+
status: "complete",
|
|
28998
|
+
source: "session-db",
|
|
28999
|
+
cachedCount: generatedNames.size
|
|
29000
|
+
});
|
|
29001
|
+
return;
|
|
29002
|
+
}
|
|
29003
|
+
const promise = checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
29004
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise };
|
|
29005
|
+
void promise.then((cachedNames) => {
|
|
29006
|
+
finishWizardTimer("generation-cache-preflight", timer, {
|
|
29007
|
+
status: "complete",
|
|
29008
|
+
source: "cache-status",
|
|
29009
|
+
cachedCount: cachedNames.size
|
|
29010
|
+
});
|
|
29011
|
+
});
|
|
29012
|
+
}, [
|
|
29013
|
+
state.step,
|
|
29014
|
+
state.extractSessionId,
|
|
29015
|
+
state.tokensPath,
|
|
29016
|
+
state.rawTokensPath,
|
|
29017
|
+
state.tokenGenerationStatus,
|
|
29018
|
+
state.selectionAgentStatus,
|
|
29019
|
+
state.compositionPhase,
|
|
29020
|
+
state.existingEntitiesStatus,
|
|
29021
|
+
state.existingEntitiesPath
|
|
29022
|
+
]);
|
|
28016
29023
|
const startGeneratePrefetch = (extractSessionId, tokensPath) => {
|
|
28017
29024
|
const args = buildGenerateArgs(extractSessionId, tokensPath);
|
|
28018
29025
|
let progressCursor = null;
|
|
@@ -28067,13 +29074,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28067
29074
|
});
|
|
28068
29075
|
return donePromise;
|
|
28069
29076
|
};
|
|
28070
|
-
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false) => {
|
|
29077
|
+
const runGenerate = async (extractSessionId, tokensPath, acceptedCount, suppressScreen = false, cachedComponents = []) => {
|
|
28071
29078
|
const timer = startWizardTimer("component-generation", {
|
|
28072
29079
|
sessionId: extractSessionId,
|
|
28073
29080
|
acceptedCount,
|
|
28074
|
-
suppressScreen
|
|
29081
|
+
suppressScreen,
|
|
29082
|
+
noCache: effectiveNoCache
|
|
28075
29083
|
});
|
|
28076
|
-
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath);
|
|
29084
|
+
const args = buildGenerateArgs(extractSessionId, tokensPath, generatePromptPath, cachedComponents);
|
|
28077
29085
|
let progressCursor = state.generateProgress;
|
|
28078
29086
|
const { donePromise } = spawnGenerateChild({
|
|
28079
29087
|
command: "node",
|
|
@@ -28143,6 +29151,25 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28143
29151
|
finishSelectionToReviewTimer("error");
|
|
28144
29152
|
}
|
|
28145
29153
|
};
|
|
29154
|
+
const finishCachedGeneration = async (sessionId2, acceptedCount) => {
|
|
29155
|
+
if (await runMapTokens2(sessionId2, true)) {
|
|
29156
|
+
finishSelectionToReviewTimer("cached");
|
|
29157
|
+
update(
|
|
29158
|
+
{
|
|
29159
|
+
acceptedCount,
|
|
29160
|
+
autoRejectedCount: 0,
|
|
29161
|
+
generateSessionId: sessionId2,
|
|
29162
|
+
generatedCount: acceptedCount,
|
|
29163
|
+
generateProgress: null,
|
|
29164
|
+
mapTokensStatus: "complete",
|
|
29165
|
+
step: "final-review"
|
|
29166
|
+
},
|
|
29167
|
+
{ clearScreen: false }
|
|
29168
|
+
);
|
|
29169
|
+
} else {
|
|
29170
|
+
finishSelectionToReviewTimer("error");
|
|
29171
|
+
}
|
|
29172
|
+
};
|
|
28146
29173
|
const advanceToPushFlow = (generatedAcceptedCount) => {
|
|
28147
29174
|
update({ generatedAcceptedCount });
|
|
28148
29175
|
void runSaveAndPush();
|
|
@@ -28327,8 +29354,14 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28327
29354
|
}
|
|
28328
29355
|
}
|
|
28329
29356
|
if (await runAgentAuthCheck("generating", true)) {
|
|
28330
|
-
|
|
28331
|
-
|
|
29357
|
+
const cacheHit = await checkGenerateCache(sid, state.tokensPath);
|
|
29358
|
+
if (cacheHit) {
|
|
29359
|
+
update({ step: "generating" });
|
|
29360
|
+
void finishCachedGeneration(sid, state.acceptedCount);
|
|
29361
|
+
} else {
|
|
29362
|
+
update({ step: "generating" });
|
|
29363
|
+
void runGenerate(sid, state.tokensPath, state.acceptedCount);
|
|
29364
|
+
}
|
|
28332
29365
|
}
|
|
28333
29366
|
return;
|
|
28334
29367
|
}
|
|
@@ -28692,7 +29725,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28692
29725
|
});
|
|
28693
29726
|
return { ok: false };
|
|
28694
29727
|
}
|
|
28695
|
-
await new Promise((
|
|
29728
|
+
await new Promise((resolve21) => setTimeout(resolve21, SAVE_CONFIRMATION_DELAY_MS));
|
|
28696
29729
|
update(nextStateAfterPrint({ skipGate: opts.skipGate, componentsPath }));
|
|
28697
29730
|
return { ok: true };
|
|
28698
29731
|
};
|
|
@@ -28769,6 +29802,12 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28769
29802
|
tokenReuseChecked.current = true;
|
|
28770
29803
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28771
29804
|
const existingTokensPath = join23(state.outDir, "tokens.json");
|
|
29805
|
+
if (effectiveNoCache) {
|
|
29806
|
+
tokenGenerationPromiseRef.current = runAgentAuthCheck(tokenNextStep).then(
|
|
29807
|
+
(ok2) => ok2 ? runGenerateTokens(state.rawTokensPath, state.outDir) : false
|
|
29808
|
+
);
|
|
29809
|
+
return;
|
|
29810
|
+
}
|
|
28772
29811
|
(async () => {
|
|
28773
29812
|
try {
|
|
28774
29813
|
await access7(existingTokensPath);
|
|
@@ -28852,7 +29891,7 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28852
29891
|
const tokenNextStep = state.projectPath ? "path-validation" : "credentials";
|
|
28853
29892
|
update({ step: tokenNextStep });
|
|
28854
29893
|
if (await runAgentAuthCheck(tokenNextStep)) {
|
|
28855
|
-
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir);
|
|
29894
|
+
tokenGenerationPromiseRef.current = runGenerateTokens(state.rawTokensPath, state.outDir, true);
|
|
28856
29895
|
}
|
|
28857
29896
|
},
|
|
28858
29897
|
onQuit: () => process.exit(0)
|
|
@@ -28951,6 +29990,29 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28951
29990
|
acceptedCount: decisions.accepted.length,
|
|
28952
29991
|
rejectedCount: decisions.rejected.length
|
|
28953
29992
|
}) : null;
|
|
29993
|
+
const preflight = generationCachePreflightRef.current;
|
|
29994
|
+
const cachePromise = preflight?.sessionId === sessionId2 ? preflight.promise : checkGenerateCacheComponents(sessionId2, state.tokensPath, true);
|
|
29995
|
+
if (!preflight || preflight.sessionId !== sessionId2) {
|
|
29996
|
+
generationCachePreflightRef.current = { sessionId: sessionId2, promise: cachePromise };
|
|
29997
|
+
}
|
|
29998
|
+
const cacheWaitStartedAt = startWizardTimer("selection-cache-restoration-wait", {
|
|
29999
|
+
sessionId: sessionId2,
|
|
30000
|
+
preflight: Boolean(preflight?.sessionId === sessionId2)
|
|
30001
|
+
});
|
|
30002
|
+
try {
|
|
30003
|
+
const cachedNames = await cachePromise;
|
|
30004
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30005
|
+
status: "complete",
|
|
30006
|
+
cachedCount: cachedNames.size
|
|
30007
|
+
});
|
|
30008
|
+
} catch (error) {
|
|
30009
|
+
finishWizardTimer("selection-cache-restoration-wait", cacheWaitStartedAt, {
|
|
30010
|
+
status: "error",
|
|
30011
|
+
error: error instanceof Error ? error.message : String(error)
|
|
30012
|
+
});
|
|
30013
|
+
finishSelectionToReviewTimer("error");
|
|
30014
|
+
throw error;
|
|
30015
|
+
}
|
|
28954
30016
|
await runScopeGate({
|
|
28955
30017
|
sessionId: sessionId2,
|
|
28956
30018
|
decisions,
|
|
@@ -28959,12 +30021,35 @@ If using a custom host configuration, make sure the space exists on that host.`
|
|
|
28959
30021
|
if (shouldGenerateAfterScopeGate({ acceptedCount })) {
|
|
28960
30022
|
const authPromise = runAgentAuthCheck("generating", true);
|
|
28961
30023
|
if (await authPromise) {
|
|
28962
|
-
|
|
28963
|
-
|
|
28964
|
-
|
|
28965
|
-
|
|
30024
|
+
const comparisonStartedAt = startWizardTimer("generation-cache-set-comparison", {
|
|
30025
|
+
sessionId: sid,
|
|
30026
|
+
acceptedCount: decisions?.accepted.length ?? 0
|
|
30027
|
+
});
|
|
30028
|
+
let cachedNames = await cachePromise;
|
|
30029
|
+
const acceptedNames = decisions?.accepted ?? [];
|
|
30030
|
+
let cacheHit = !effectiveNoCache && acceptedNames.length > 0 && acceptedNames.every((name) => cachedNames.has(name));
|
|
30031
|
+
if (!cacheHit && !effectiveNoCache && acceptedNames.length > 0) {
|
|
30032
|
+
cachedNames = await checkGenerateCacheComponents(sid, state.tokensPath, true);
|
|
30033
|
+
cacheHit = acceptedNames.every((name) => cachedNames.has(name));
|
|
30034
|
+
}
|
|
30035
|
+
finishWizardTimer("generation-cache-set-comparison", comparisonStartedAt, {
|
|
30036
|
+
status: "complete",
|
|
30037
|
+
cacheHit,
|
|
30038
|
+
cachedCount: cachedNames.size,
|
|
30039
|
+
acceptedCount: acceptedNames.length
|
|
28966
30040
|
});
|
|
28967
|
-
|
|
30041
|
+
if (cacheHit) {
|
|
30042
|
+
void finishCachedGeneration(sid, acceptedCount);
|
|
30043
|
+
} else {
|
|
30044
|
+
const acceptedNameSet = new Set(acceptedNames);
|
|
30045
|
+
const restoredCachedNames = [...cachedNames].filter((name) => acceptedNameSet.has(name));
|
|
30046
|
+
update({
|
|
30047
|
+
step: "generating",
|
|
30048
|
+
generateProgress: null,
|
|
30049
|
+
acceptedCount
|
|
30050
|
+
});
|
|
30051
|
+
void runGenerate(sid, state.tokensPath, acceptedCount, false, restoredCachedNames);
|
|
30052
|
+
}
|
|
28968
30053
|
} else {
|
|
28969
30054
|
finishSelectionToReviewTimer("error");
|
|
28970
30055
|
}
|
|
@@ -29330,7 +30415,7 @@ function registerImportCommand(program) {
|
|
|
29330
30415
|
"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",
|
|
29331
30416
|
(v, acc) => [...acc, v],
|
|
29332
30417
|
[]
|
|
29333
|
-
).action(async (opts) => {
|
|
30418
|
+
).option("--no-cache", "Re-run all steps even if output already exists").action(async (opts) => {
|
|
29334
30419
|
const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
|
|
29335
30420
|
if (opts.tokens !== void 0) {
|
|
29336
30421
|
const { access: access9 } = await import("node:fs/promises");
|
|
@@ -29367,6 +30452,7 @@ function registerImportCommand(program) {
|
|
|
29367
30452
|
...resolvedModel ? { initialModel: resolvedModel } : {},
|
|
29368
30453
|
initialProjectPath: opts.project !== "." ? normalizePath(opts.project) : void 0,
|
|
29369
30454
|
...buildCompositionForwardingOptions(opts),
|
|
30455
|
+
noCache: opts.cache === false,
|
|
29370
30456
|
skipMapTokens: false,
|
|
29371
30457
|
livePreview: true,
|
|
29372
30458
|
generatePromptPath: creds.generatePromptPath,
|
|
@@ -29454,7 +30540,7 @@ async function pathExists3(path) {
|
|
|
29454
30540
|
return access8(path).then(() => true).catch(() => false);
|
|
29455
30541
|
}
|
|
29456
30542
|
function runSpawn(cmd, args, opts = {}) {
|
|
29457
|
-
return new Promise((
|
|
30543
|
+
return new Promise((resolve21) => {
|
|
29458
30544
|
const child = spawn6(cmd, args, {
|
|
29459
30545
|
cwd: opts.cwd,
|
|
29460
30546
|
env: opts.env ?? process.env,
|
|
@@ -29466,7 +30552,7 @@ function runSpawn(cmd, args, opts = {}) {
|
|
|
29466
30552
|
const settle = (result) => {
|
|
29467
30553
|
if (settled) return;
|
|
29468
30554
|
settled = true;
|
|
29469
|
-
|
|
30555
|
+
resolve21(result);
|
|
29470
30556
|
};
|
|
29471
30557
|
child.on("error", (err) => settle({ exitCode: 1, stdout: "", stderr: err.message }));
|
|
29472
30558
|
child.stdout.on("data", (d) => {
|
|
@@ -30667,13 +31753,13 @@ function PrerequisitesScreen({
|
|
|
30667
31753
|
const driver = {
|
|
30668
31754
|
...base,
|
|
30669
31755
|
emit: (event) => setEvents((current) => [...current, event]),
|
|
30670
|
-
confirm: (question, defaultYes = true) => new Promise((
|
|
31756
|
+
confirm: (question, defaultYes = true) => new Promise((resolve21) => {
|
|
30671
31757
|
setConfirm({
|
|
30672
31758
|
question,
|
|
30673
31759
|
defaultYes,
|
|
30674
31760
|
resolve: (answer) => {
|
|
30675
31761
|
setConfirm(null);
|
|
30676
|
-
|
|
31762
|
+
resolve21(answer);
|
|
30677
31763
|
}
|
|
30678
31764
|
});
|
|
30679
31765
|
})
|
|
@@ -30748,8 +31834,8 @@ function SetupScreen({
|
|
|
30748
31834
|
useEffect21(() => {
|
|
30749
31835
|
if (startedRef.current) return;
|
|
30750
31836
|
startedRef.current = true;
|
|
30751
|
-
const runScreen = (build) => new Promise((
|
|
30752
|
-
setScreen(build(
|
|
31837
|
+
const runScreen = (build) => new Promise((resolve21) => {
|
|
31838
|
+
setScreen(build(resolve21));
|
|
30753
31839
|
});
|
|
30754
31840
|
void (async () => {
|
|
30755
31841
|
const results = [];
|
|
@@ -31357,8 +32443,11 @@ var init_source_call_site_evidence = __esm({
|
|
|
31357
32443
|
});
|
|
31358
32444
|
|
|
31359
32445
|
// packages/experience-design-system-cli-legacy/src/analyze/extract-command.ts
|
|
31360
|
-
import { mkdir as mkdir6, readdir as readdir3, readFile as
|
|
31361
|
-
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as
|
|
32446
|
+
import { mkdir as mkdir6, readdir as readdir3, readFile as readFile19, stat as stat6 } from "node:fs/promises";
|
|
32447
|
+
import { isAbsolute as isAbsolute2, join as join27, relative as relative2, resolve as resolve19 } from "node:path";
|
|
32448
|
+
function resolveExtractNoCache(opts) {
|
|
32449
|
+
return opts.noCache === true || opts.cache === false;
|
|
32450
|
+
}
|
|
31362
32451
|
function isDenylistedNoiseFile(name) {
|
|
31363
32452
|
return DENYLISTED_EXACT_FILE_NAMES.has(name) || DENYLISTED_FILE_NAME_PATTERNS.some((pattern) => pattern.test(name));
|
|
31364
32453
|
}
|
|
@@ -31372,12 +32461,12 @@ async function retryDatabaseWrite(operation, attempts = 8) {
|
|
|
31372
32461
|
} catch (error) {
|
|
31373
32462
|
const message = error instanceof Error ? error.message : String(error);
|
|
31374
32463
|
if (!/database is locked|database is busy/i.test(message) || attempt >= attempts) throw error;
|
|
31375
|
-
await new Promise((
|
|
32464
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(250 * attempt, 2e3)));
|
|
31376
32465
|
}
|
|
31377
32466
|
}
|
|
31378
32467
|
}
|
|
31379
32468
|
function resolveFromProjectRoot(projectRoot, inputPath) {
|
|
31380
|
-
return isAbsolute2(inputPath) ? inputPath :
|
|
32469
|
+
return isAbsolute2(inputPath) ? inputPath : resolve19(projectRoot, inputPath);
|
|
31381
32470
|
}
|
|
31382
32471
|
async function pathExists4(path) {
|
|
31383
32472
|
return Boolean(await stat6(path).catch(() => null));
|
|
@@ -31424,7 +32513,7 @@ async function readCandidateFiles(components, extraFiles = []) {
|
|
|
31424
32513
|
await Promise.all(
|
|
31425
32514
|
[...paths].map(async (p) => {
|
|
31426
32515
|
try {
|
|
31427
|
-
const content = await
|
|
32516
|
+
const content = await readFile19(p, "utf8");
|
|
31428
32517
|
out.push({ path: p, content });
|
|
31429
32518
|
} catch {
|
|
31430
32519
|
}
|
|
@@ -31437,7 +32526,8 @@ function registerInternalExtractCommand(program) {
|
|
|
31437
32526
|
"--resolve-unreachable <mode>",
|
|
31438
32527
|
"Retry pass for unresolved Svelte Props types: 'auto' (default), 'always', or 'never'",
|
|
31439
32528
|
"auto"
|
|
31440
|
-
).action(async (opts) => {
|
|
32529
|
+
).option("--no-cache", "Re-run extraction even when all source files are unchanged").action(async (opts) => {
|
|
32530
|
+
const noCache = resolveExtractNoCache(opts);
|
|
31441
32531
|
const resolveUnreachable = (() => {
|
|
31442
32532
|
const v = opts.resolveUnreachable ?? "auto";
|
|
31443
32533
|
if (v !== "auto" && v !== "always" && v !== "never") {
|
|
@@ -31447,7 +32537,7 @@ function registerInternalExtractCommand(program) {
|
|
|
31447
32537
|
}
|
|
31448
32538
|
return v;
|
|
31449
32539
|
})();
|
|
31450
|
-
const projectRoot =
|
|
32540
|
+
const projectRoot = resolve19(opts.project);
|
|
31451
32541
|
const outDir = join27(projectRoot, ".contentful");
|
|
31452
32542
|
let sourceDirectory;
|
|
31453
32543
|
if (opts.dir !== void 0) {
|
|
@@ -31471,16 +32561,50 @@ function registerInternalExtractCommand(program) {
|
|
|
31471
32561
|
process.stderr.write(`progress=scan-done:${sourceFiles.length}
|
|
31472
32562
|
`);
|
|
31473
32563
|
}
|
|
31474
|
-
const
|
|
31475
|
-
|
|
31476
|
-
|
|
32564
|
+
const extractionCacheDb = openPipelineDb();
|
|
32565
|
+
let extraction;
|
|
32566
|
+
let extractionCacheHits = 0;
|
|
32567
|
+
try {
|
|
32568
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32569
|
+
const cachedByPath = /* @__PURE__ */ new Map();
|
|
32570
|
+
if (!noCache && sourceFiles.length > 0) {
|
|
32571
|
+
const hashes = await Promise.all(
|
|
32572
|
+
sourceFiles.map(async (filePath) => [filePath, await hashFile(filePath)])
|
|
32573
|
+
);
|
|
32574
|
+
for (const [filePath, fileHash] of hashes) {
|
|
32575
|
+
cachedByPath.set(filePath, lookupExtractCache(extractionCacheDb, fileHash, cacheVersion));
|
|
32576
|
+
}
|
|
32577
|
+
}
|
|
32578
|
+
const allFilesCached = !noCache && sourceFiles.length > 0 && sourceFiles.every((filePath) => cachedByPath.get(filePath) !== null);
|
|
32579
|
+
if (allFilesCached) {
|
|
32580
|
+
const cachedComponents = sourceFiles.flatMap((filePath) => cachedByPath.get(filePath).components);
|
|
32581
|
+
extractionCacheHits = sourceFiles.length;
|
|
32582
|
+
extraction = { components: cachedComponents, warnings: [], exclusions: [] };
|
|
31477
32583
|
if (!process.stdout.isTTY) {
|
|
31478
|
-
process.stderr.write(
|
|
31479
|
-
`
|
|
32584
|
+
process.stderr.write(
|
|
32585
|
+
`progress=extract:${sourceFiles.length}/${sourceFiles.length}:${cachedComponents.length}
|
|
32586
|
+
`
|
|
32587
|
+
);
|
|
31480
32588
|
}
|
|
31481
|
-
|
|
31482
|
-
|
|
31483
|
-
|
|
32589
|
+
getDebugLogger().event("analyze", "extract.cache-hit", {
|
|
32590
|
+
files: sourceFiles.length,
|
|
32591
|
+
components: cachedComponents.length
|
|
32592
|
+
});
|
|
32593
|
+
} else {
|
|
32594
|
+
extraction = await extractComponents(
|
|
32595
|
+
sourceFiles,
|
|
32596
|
+
({ filesProcessed, componentsFound }) => {
|
|
32597
|
+
if (!process.stdout.isTTY) {
|
|
32598
|
+
process.stderr.write(`progress=extract:${filesProcessed}/${sourceFiles.length}:${componentsFound}
|
|
32599
|
+
`);
|
|
32600
|
+
}
|
|
32601
|
+
},
|
|
32602
|
+
{ resolveUnreachable, projectRoot }
|
|
32603
|
+
);
|
|
32604
|
+
}
|
|
32605
|
+
} finally {
|
|
32606
|
+
extractionCacheDb.close();
|
|
32607
|
+
}
|
|
31484
32608
|
await mkdir6(outDir, { recursive: true });
|
|
31485
32609
|
const db = openPipelineDb();
|
|
31486
32610
|
const { sessionId: sessionId2 } = getOrCreateSession(db, void 0, void 0, {
|
|
@@ -31495,6 +32619,25 @@ function registerInternalExtractCommand(program) {
|
|
|
31495
32619
|
const stepId = createStep(db, sessionId2, "analyze extract", {
|
|
31496
32620
|
project: projectRoot
|
|
31497
32621
|
});
|
|
32622
|
+
if (extractionCacheHits === 0 && !noCache) {
|
|
32623
|
+
const cacheVersion = await getCliCacheVersion();
|
|
32624
|
+
const componentsBySourcePath = /* @__PURE__ */ new Map();
|
|
32625
|
+
for (const component of extraction.components) {
|
|
32626
|
+
if (!component.sourcePath) continue;
|
|
32627
|
+
const components = componentsBySourcePath.get(component.sourcePath) ?? [];
|
|
32628
|
+
components.push(component);
|
|
32629
|
+
componentsBySourcePath.set(component.sourcePath, components);
|
|
32630
|
+
}
|
|
32631
|
+
for (const filePath of sourceFiles) {
|
|
32632
|
+
storeExtractCache(
|
|
32633
|
+
db,
|
|
32634
|
+
filePath,
|
|
32635
|
+
await hashFile(filePath),
|
|
32636
|
+
cacheVersion,
|
|
32637
|
+
componentsBySourcePath.get(filePath) ?? []
|
|
32638
|
+
);
|
|
32639
|
+
}
|
|
32640
|
+
}
|
|
31498
32641
|
const classifiedComponents = extraction.components.map(preClassifyComponent);
|
|
31499
32642
|
for (const exclusion of extraction.exclusions ?? []) {
|
|
31500
32643
|
getDebugLogger().event("filter", "extract.excluded", { ...exclusion });
|
|
@@ -31599,6 +32742,7 @@ var init_extract_command = __esm({
|
|
|
31599
32742
|
"use strict";
|
|
31600
32743
|
init_src2();
|
|
31601
32744
|
init_db();
|
|
32745
|
+
init_cache_keys();
|
|
31602
32746
|
init_cycle_detection();
|
|
31603
32747
|
init_resolve_mapping();
|
|
31604
32748
|
init_manifest_doc_evidence();
|
|
@@ -31697,7 +32841,7 @@ __export(program_exports, {
|
|
|
31697
32841
|
});
|
|
31698
32842
|
import { spawn as spawn7 } from "node:child_process";
|
|
31699
32843
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
31700
|
-
import { dirname as dirname18, join as join28, resolve as
|
|
32844
|
+
import { dirname as dirname18, join as join28, resolve as resolve20 } from "node:path";
|
|
31701
32845
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
31702
32846
|
import { Command } from "commander";
|
|
31703
32847
|
async function runBuild(opts) {
|
|
@@ -31727,7 +32871,7 @@ function resolveBedrockFromAncestors(actionCommand) {
|
|
|
31727
32871
|
}
|
|
31728
32872
|
function registerBuildCommand(program) {
|
|
31729
32873
|
program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").helpOption(false).action(async () => {
|
|
31730
|
-
const pkgRoot =
|
|
32874
|
+
const pkgRoot = resolve20(dirname18(fileURLToPath3(import.meta.url)), "..", "..");
|
|
31731
32875
|
process.stderr.write("\u2699 Building from source...\n");
|
|
31732
32876
|
const { exitCode } = await runBuild({
|
|
31733
32877
|
spawnFn: () => spawn7("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|