@contentful/experience-design-system-cli 2.26.1-dev-build-a852362.0 → 2.26.1-dev-build-f03f014.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 +14 -10
- package/dist/src/index.js +34937 -9
- package/dist/src/lib/cli-path.d.ts +4 -0
- package/dist/src/runs/export-helpers.d.ts +1 -12
- package/dist/src/runs/push-helpers.d.ts +1 -6
- package/package.json +12 -7
- package/skills/generate-components.md +427 -0
- package/skills/generate-tokens.md +194 -0
- package/skills/select-components.md +224 -0
- package/dist/src/analytics/apply.js +0 -30
- package/dist/src/analytics/client.js +0 -81
- package/dist/src/analytics/constants.js +0 -4
- package/dist/src/analytics/env.js +0 -14
- package/dist/src/analytics/exit.js +0 -24
- package/dist/src/analytics/index.js +0 -9
- package/dist/src/analytics/normalize.js +0 -18
- package/dist/src/analytics/os.js +0 -13
- package/dist/src/analytics/session.js +0 -15
- package/dist/src/analytics/tracker.js +0 -126
- package/dist/src/analytics/types.js +0 -1
- package/dist/src/analyze/build-analyze-view-rows.js +0 -63
- package/dist/src/analyze/command.js +0 -599
- package/dist/src/analyze/composite-closure.js +0 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.js +0 -22
- package/dist/src/analyze/composition/agent-parser/extract-parser.js +0 -44
- package/dist/src/analyze/composition/agent-parser/load-prompt.js +0 -31
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +0 -88
- package/dist/src/analyze/composition/agent-parser/sandbox.js +0 -187
- package/dist/src/analyze/composition/apply-mapping.js +0 -67
- package/dist/src/analyze/composition/candidate-critic-agent.js +0 -39
- package/dist/src/analyze/composition/candidate-critic.js +0 -63
- package/dist/src/analyze/composition/candidate-files.js +0 -131
- package/dist/src/analyze/composition/composition-cache-key.js +0 -19
- package/dist/src/analyze/composition/interchange-schema.js +0 -61
- package/dist/src/analyze/composition/manifest-doc-evidence.js +0 -136
- package/dist/src/analyze/composition/merge-edges.js +0 -70
- package/dist/src/analyze/composition/parse-map-edges.js +0 -55
- package/dist/src/analyze/composition/resolve-mapping-cli.js +0 -29
- package/dist/src/analyze/composition/resolve-mapping.js +0 -111
- package/dist/src/analyze/cycle-detection.js +0 -234
- package/dist/src/analyze/cycle-view.js +0 -28
- package/dist/src/analyze/fuzzy-search.js +0 -55
- package/dist/src/analyze/issue-inheritance.js +0 -108
- package/dist/src/analyze/lineage.js +0 -0
- package/dist/src/analyze/scope-gate-cascade.js +0 -170
- package/dist/src/analyze/search-neighborhood.js +0 -56
- package/dist/src/analyze/select/command.js +0 -484
- package/dist/src/analyze/select/index.js +0 -5
- package/dist/src/analyze/select/parser.js +0 -53
- package/dist/src/analyze/select/persistence.js +0 -80
- package/dist/src/analyze/select/preview-annotations.js +0 -62
- package/dist/src/analyze/select/stdout.js +0 -3
- package/dist/src/analyze/select/tui/App.js +0 -483
- package/dist/src/analyze/select/tui/components/ComponentDetail.js +0 -48
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +0 -125
- package/dist/src/analyze/select/tui/components/FieldEditor.js +0 -1131
- package/dist/src/analyze/select/tui/components/FinalizeDialog.js +0 -36
- package/dist/src/analyze/select/tui/components/GotoBanner.js +0 -30
- package/dist/src/analyze/select/tui/components/GroupedSidebar.js +0 -517
- package/dist/src/analyze/select/tui/components/HelpOverlay.js +0 -17
- package/dist/src/analyze/select/tui/components/JsonEditor.js +0 -131
- package/dist/src/analyze/select/tui/components/JsonPanel.js +0 -66
- package/dist/src/analyze/select/tui/components/LineagePanel.js +0 -22
- package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +0 -29
- package/dist/src/analyze/select/tui/components/QuitDialog.js +0 -14
- package/dist/src/analyze/select/tui/components/RationalePanel.js +0 -80
- package/dist/src/analyze/select/tui/components/Sidebar.js +0 -92
- package/dist/src/analyze/select/tui/components/SourcePanel.js +0 -52
- package/dist/src/analyze/select/tui/components/StatusBar.js +0 -7
- package/dist/src/analyze/select/tui/components/TopBar.js +0 -10
- package/dist/src/analyze/select/tui/components/removed-components-text.js +0 -11
- package/dist/src/analyze/select/tui/hooks/scroll-offset.js +0 -26
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +0 -66
- package/dist/src/analyze/select/tui/hooks/useKeymap.js +0 -67
- package/dist/src/analyze/select/tui/hooks/useSession.js +0 -52
- package/dist/src/analyze/select/tui/hooks/useUndo.js +0 -26
- package/dist/src/analyze/select/tui/theme.js +0 -28
- package/dist/src/analyze/select/types.js +0 -39
- package/dist/src/analyze/select-agent/command.js +0 -558
- package/dist/src/analyze/select-agent/context-builder.js +0 -197
- package/dist/src/analyze/select-agent/show-rationale.js +0 -92
- package/dist/src/analyze/selection-cascade.js +0 -19
- package/dist/src/analyze/slot-graph.js +0 -17
- package/dist/src/analyze/tui/AnalyzeView.js +0 -64
- package/dist/src/apply/api-client.js +0 -440
- package/dist/src/apply/command.js +0 -845
- package/dist/src/apply/manifest.js +0 -1
- package/dist/src/apply/preview-utils.js +0 -26
- package/dist/src/apply/tui/SelectView.js +0 -34
- package/dist/src/apply/tui/ServerApplyView.js +0 -49
- package/dist/src/apply/tui/ServerPreviewView.js +0 -23
- package/dist/src/credentials-store.js +0 -74
- package/dist/src/generate/command.js +0 -597
- package/dist/src/generate/edit/command.js +0 -127
- package/dist/src/generate/tui/GenerateView.js +0 -10
- package/dist/src/host-utils.js +0 -26
- package/dist/src/import/agent-model-resolve.js +0 -35
- package/dist/src/import/auto-filter-resolve.js +0 -16
- package/dist/src/import/command.js +0 -380
- package/dist/src/import/cycle-auto-reject.js +0 -14
- package/dist/src/import/orchestrator.js +0 -603
- package/dist/src/import/path-utils.js +0 -30
- package/dist/src/import/picker-dispatch.js +0 -44
- package/dist/src/import/print-prompt.js +0 -31
- package/dist/src/import/strip-allowed-components.js +0 -22
- package/dist/src/import/tui/CustomPromptBanner.js +0 -8
- package/dist/src/import/tui/WizardApp.js +0 -1670
- package/dist/src/import/tui/ai-flag.js +0 -6
- package/dist/src/import/tui/auto-filter-error.js +0 -29
- package/dist/src/import/tui/autocomplete.js +0 -32
- package/dist/src/import/tui/components/AutoFilterBanner.js +0 -19
- package/dist/src/import/tui/components/CounterStrip.js +0 -12
- package/dist/src/import/tui/components/LegendEntry.js +0 -6
- package/dist/src/import/tui/cycle-panel-scroll.js +0 -33
- package/dist/src/import/tui/final-review-host.js +0 -25
- package/dist/src/import/tui/group-collapse.js +0 -11
- package/dist/src/import/tui/history.js +0 -53
- package/dist/src/import/tui/hooks/useLineage.js +0 -50
- package/dist/src/import/tui/hooks/useOverlayPanel.js +0 -27
- package/dist/src/import/tui/lineage-layout.js +0 -82
- package/dist/src/import/tui/merge-ai-decisions.js +0 -22
- package/dist/src/import/tui/push-decision-gate-helpers.js +0 -8
- package/dist/src/import/tui/push-progress.js +0 -1
- package/dist/src/import/tui/run-print-files-helpers.js +0 -8
- package/dist/src/import/tui/run-teaser.js +0 -9
- package/dist/src/import/tui/runLivePreview.js +0 -82
- package/dist/src/import/tui/runScopeGate.js +0 -28
- package/dist/src/import/tui/scope-gate-columns.js +0 -94
- package/dist/src/import/tui/scope-gate-host.js +0 -28
- package/dist/src/import/tui/sidebar-width.js +0 -3
- package/dist/src/import/tui/spawn-generate.js +0 -53
- package/dist/src/import/tui/step-filters.js +0 -42
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +0 -726
- package/dist/src/import/tui/steps/AtomicScopeGateStep.js +0 -210
- package/dist/src/import/tui/steps/CredentialsStep.js +0 -108
- package/dist/src/import/tui/steps/DoneStep.js +0 -24
- package/dist/src/import/tui/steps/ErrorStep.js +0 -16
- package/dist/src/import/tui/steps/GateStep.js +0 -22
- package/dist/src/import/tui/steps/GenerateReviewStep.js +0 -1618
- package/dist/src/import/tui/steps/PathValidationStep.js +0 -152
- package/dist/src/import/tui/steps/PreviewStep.js +0 -37
- package/dist/src/import/tui/steps/PreviewValidationErrorStep.js +0 -23
- package/dist/src/import/tui/steps/PushDecisionGateStep.js +0 -73
- package/dist/src/import/tui/steps/PushingStep.js +0 -24
- package/dist/src/import/tui/steps/RunningStep.js +0 -21
- package/dist/src/import/tui/steps/ScopeGateStep.js +0 -907
- package/dist/src/import/tui/steps/TokenInputStep.js +0 -88
- package/dist/src/import/tui/steps/WelcomeStep.js +0 -34
- package/dist/src/import/tui/steps/WizardPreviewStep.js +0 -169
- package/dist/src/import/tui/steps/auto-reject-decision.js +0 -9
- package/dist/src/import/tui/steps/breaking-change-format.js +0 -24
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
- package/dist/src/import/tui/steps/preview-diff.js +0 -175
- package/dist/src/import/tui/useFinalizePreview.js +0 -0
- package/dist/src/import/tui/useLivePreview.js +0 -122
- package/dist/src/import/tui/wizard-422-helpers.js +0 -60
- package/dist/src/import/tui/wizard-generate-progress.js +0 -25
- package/dist/src/import/tui/wizard-save-flow.js +0 -20
- package/dist/src/import/tui/wizard-state-transitions.js +0 -32
- package/dist/src/lib/agent-model-options.js +0 -15
- package/dist/src/lib/command-options.js +0 -30
- package/dist/src/lib/composition-mode.js +0 -39
- package/dist/src/lib/contentful-urls.js +0 -27
- package/dist/src/lib/debug-logger.js +0 -229
- package/dist/src/lib/debug-preamble.js +0 -33
- package/dist/src/lib/error-parser.js +0 -269
- package/dist/src/lib/prompt-overrides.js +0 -69
- package/dist/src/lib/terminal-capabilities.js +0 -51
- package/dist/src/lib/user-agent.js +0 -29
- package/dist/src/output/format.js +0 -110
- package/dist/src/print/command.js +0 -221
- package/dist/src/print/validate/tui/ValidateView.js +0 -37
- package/dist/src/print/validate/validators/cdf-validator.js +0 -104
- package/dist/src/print/validate/validators/dtcg-validator.js +0 -110
- package/dist/src/print/validate/validators/format-errors.js +0 -18
- package/dist/src/program.js +0 -105
- package/dist/src/runs/export-helpers.js +0 -59
- package/dist/src/runs/fingerprint.js +0 -75
- package/dist/src/runs/ls-command.js +0 -137
- package/dist/src/runs/modify-launcher.js +0 -42
- package/dist/src/runs/path-prompt.js +0 -72
- package/dist/src/runs/push-creds-prompt.js +0 -39
- package/dist/src/runs/push-helpers.js +0 -72
- package/dist/src/runs/push-launcher.js +0 -77
- package/dist/src/runs/replay-helpers.js +0 -164
- package/dist/src/runs/resolve-run-target.js +0 -45
- package/dist/src/runs/run-picker-mount.js +0 -72
- package/dist/src/runs/run-picker.js +0 -129
- package/dist/src/runs/save-conflict.js +0 -56
- package/dist/src/runs/save-path-resolver.js +0 -75
- package/dist/src/runs/staleness.js +0 -140
- package/dist/src/runs/store.js +0 -136
- package/dist/src/session/cache-keys.js +0 -44
- package/dist/src/session/command.js +0 -261
- package/dist/src/session/db.js +0 -1538
- package/dist/src/session/migration.js +0 -117
- package/dist/src/session/session-id.js +0 -212
- package/dist/src/session/stats.js +0 -89
- package/dist/src/setup/analytics-prompt.js +0 -24
- package/dist/src/setup/auto-filter-prompt.js +0 -24
- package/dist/src/setup/command.js +0 -966
- package/dist/src/setup/composition-mode-prompt.js +0 -37
- package/dist/src/setup/debug-mode-prompt.js +0 -22
- package/dist/src/types.js +0 -1
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
3
|
-
const SCANNED_FILE_EXTENSIONS = new Set(['.astro', '.js', '.jsx', '.svelte', '.ts', '.tsx', '.vue']);
|
|
4
|
-
const IMPORT_PATTERN = /import\s+(?:type\s+)?(.+?)\s+from\s+['"]([^'"]+)['"]/g;
|
|
5
|
-
const EXPORT_NAMED_PATTERN = /export\s+(?:const|function|class|type|interface|enum)\s+([A-Za-z0-9_]+)/g;
|
|
6
|
-
const EXPORT_DEFAULT_PATTERN = /export\s+default\s+([A-Za-z0-9_]+)/g;
|
|
7
|
-
const EXPORT_LIST_PATTERN = /export\s*\{([^}]+)\}/g;
|
|
8
|
-
const RESOLVER_HINT_PATTERN = /(resolver|registry|componentmap|component-map|componentresolver|resolvecomponent)/i;
|
|
9
|
-
const MAX_COMPONENT_SOURCE_CHARS = 8_000;
|
|
10
|
-
const MAX_SIBLING_FILES = 5;
|
|
11
|
-
const MAX_SIBLING_SNIPPET_CHARS = 1_200;
|
|
12
|
-
const MAX_REFERENCE_SNIPPETS = 3;
|
|
13
|
-
const MAX_REFERENCE_CHARS = 800;
|
|
14
|
-
function truncateText(text, maxChars) {
|
|
15
|
-
if (text.length <= maxChars)
|
|
16
|
-
return text;
|
|
17
|
-
return text.slice(0, maxChars) + '\n/* truncated */';
|
|
18
|
-
}
|
|
19
|
-
function isWithinRoot(path, root) {
|
|
20
|
-
const relativePath = relative(root, path);
|
|
21
|
-
return relativePath !== '..' && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath);
|
|
22
|
-
}
|
|
23
|
-
function parseImportedNames(importClause) {
|
|
24
|
-
const names = [];
|
|
25
|
-
const parts = importClause.split(',').map((part) => part.trim());
|
|
26
|
-
for (const part of parts) {
|
|
27
|
-
if (!part)
|
|
28
|
-
continue;
|
|
29
|
-
if (part.startsWith('{') && part.endsWith('}')) {
|
|
30
|
-
for (const named of part
|
|
31
|
-
.slice(1, -1)
|
|
32
|
-
.split(',')
|
|
33
|
-
.map((item) => item.trim())
|
|
34
|
-
.filter(Boolean)) {
|
|
35
|
-
const [local] = named.split(/\s+as\s+/i);
|
|
36
|
-
if (local)
|
|
37
|
-
names.push(local.trim());
|
|
38
|
-
}
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
const [local] = part.split(/\s+as\s+/i);
|
|
42
|
-
if (local)
|
|
43
|
-
names.push(local.trim());
|
|
44
|
-
}
|
|
45
|
-
return [...new Set(names)];
|
|
46
|
-
}
|
|
47
|
-
function resolveLocalImportPath(source, componentDirectory, root, filePaths) {
|
|
48
|
-
const basePath = resolve(componentDirectory, source);
|
|
49
|
-
const candidates = [
|
|
50
|
-
basePath,
|
|
51
|
-
...[...SCANNED_FILE_EXTENSIONS].map((extension) => `${basePath}${extension}`),
|
|
52
|
-
...[...SCANNED_FILE_EXTENSIONS].map((extension) => join(basePath, `index${extension}`)),
|
|
53
|
-
];
|
|
54
|
-
for (const candidate of candidates) {
|
|
55
|
-
if (filePaths.has(candidate) && isWithinRoot(candidate, root)) {
|
|
56
|
-
return relative(root, candidate);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (isWithinRoot(basePath, root)) {
|
|
60
|
-
return relative(root, basePath);
|
|
61
|
-
}
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
function parseImports(sourceText, componentDirectory, root, filePaths) {
|
|
65
|
-
const imports = [];
|
|
66
|
-
for (const match of sourceText.matchAll(IMPORT_PATTERN)) {
|
|
67
|
-
const importClause = match[1]?.trim() ?? '';
|
|
68
|
-
const source = match[2]?.trim() ?? '';
|
|
69
|
-
const local = source.startsWith('.');
|
|
70
|
-
const names = parseImportedNames(importClause);
|
|
71
|
-
const record = { source, names, local };
|
|
72
|
-
if (local) {
|
|
73
|
-
record.resolvedPath = resolveLocalImportPath(source, componentDirectory, root, filePaths);
|
|
74
|
-
}
|
|
75
|
-
imports.push(record);
|
|
76
|
-
}
|
|
77
|
-
return imports;
|
|
78
|
-
}
|
|
79
|
-
function parseExports(sourceText) {
|
|
80
|
-
const exports = new Set();
|
|
81
|
-
for (const match of sourceText.matchAll(EXPORT_NAMED_PATTERN)) {
|
|
82
|
-
if (match[1])
|
|
83
|
-
exports.add(match[1]);
|
|
84
|
-
}
|
|
85
|
-
for (const match of sourceText.matchAll(EXPORT_DEFAULT_PATTERN)) {
|
|
86
|
-
if (match[1])
|
|
87
|
-
exports.add(`default:${match[1]}`);
|
|
88
|
-
}
|
|
89
|
-
for (const match of sourceText.matchAll(EXPORT_LIST_PATTERN)) {
|
|
90
|
-
const items = match[1]
|
|
91
|
-
?.split(',')
|
|
92
|
-
.map((item) => item.trim())
|
|
93
|
-
.filter(Boolean) ?? [];
|
|
94
|
-
for (const item of items)
|
|
95
|
-
exports.add(item);
|
|
96
|
-
}
|
|
97
|
-
return [...exports];
|
|
98
|
-
}
|
|
99
|
-
function extractSnippet(text, token, maxChars) {
|
|
100
|
-
const index = text.indexOf(token);
|
|
101
|
-
if (index === -1)
|
|
102
|
-
return truncateText(text, maxChars);
|
|
103
|
-
const start = Math.max(0, text.lastIndexOf('\n', Math.max(0, index - Math.floor(maxChars / 2))) + 1);
|
|
104
|
-
const endBoundary = text.indexOf('\n', index + Math.floor(maxChars / 2));
|
|
105
|
-
const end = endBoundary === -1 ? text.length : endBoundary;
|
|
106
|
-
return truncateText(text.slice(start, end).trim(), maxChars);
|
|
107
|
-
}
|
|
108
|
-
function summarizeSiblingFiles(root, files, currentFile) {
|
|
109
|
-
return files
|
|
110
|
-
.filter((file) => file.absolutePath !== currentFile)
|
|
111
|
-
.slice(0, MAX_SIBLING_FILES)
|
|
112
|
-
.map((file) => ({
|
|
113
|
-
path: relative(root, file.absolutePath),
|
|
114
|
-
exports: parseExports(file.text),
|
|
115
|
-
codeSnippet: truncateText(file.text, MAX_SIBLING_SNIPPET_CHARS),
|
|
116
|
-
}));
|
|
117
|
-
}
|
|
118
|
-
function findResolverReferences(root, files, componentName, currentFile) {
|
|
119
|
-
return files
|
|
120
|
-
.filter((file) => file.absolutePath !== currentFile)
|
|
121
|
-
.filter((file) => file.text.includes(componentName))
|
|
122
|
-
.filter((file) => RESOLVER_HINT_PATTERN.test(file.absolutePath) || RESOLVER_HINT_PATTERN.test(file.text))
|
|
123
|
-
.slice(0, MAX_REFERENCE_SNIPPETS)
|
|
124
|
-
.map((file) => ({
|
|
125
|
-
path: relative(root, file.absolutePath),
|
|
126
|
-
snippet: extractSnippet(file.text, componentName, MAX_REFERENCE_CHARS),
|
|
127
|
-
}));
|
|
128
|
-
}
|
|
129
|
-
function findParentUsageSite(root, files, componentName, currentFile) {
|
|
130
|
-
const usagePattern = new RegExp(`<${componentName}\\b|\\b${componentName}\\s*[),}]|\\b${componentName}\\s*:`);
|
|
131
|
-
const candidates = files.filter((file) => file.absolutePath !== currentFile &&
|
|
132
|
-
usagePattern.test(file.text) &&
|
|
133
|
-
!file.text.startsWith('// stub') &&
|
|
134
|
-
!RESOLVER_HINT_PATTERN.test(file.absolutePath) &&
|
|
135
|
-
!RESOLVER_HINT_PATTERN.test(file.text));
|
|
136
|
-
const match = candidates[0];
|
|
137
|
-
if (!match)
|
|
138
|
-
return undefined;
|
|
139
|
-
return {
|
|
140
|
-
path: relative(root, match.absolutePath),
|
|
141
|
-
snippet: extractSnippet(match.text, componentName, MAX_REFERENCE_CHARS),
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
export async function buildRepoContextIndex(root, filePaths) {
|
|
145
|
-
if (filePaths.length === 0)
|
|
146
|
-
return null;
|
|
147
|
-
const resolvedRoot = resolve(root);
|
|
148
|
-
const files = await Promise.all(filePaths.map(async (absolutePath) => ({
|
|
149
|
-
absolutePath,
|
|
150
|
-
relativePath: relative(resolvedRoot, absolutePath),
|
|
151
|
-
directory: dirname(absolutePath),
|
|
152
|
-
text: await readFile(absolutePath, 'utf8').catch(() => ''),
|
|
153
|
-
})));
|
|
154
|
-
const byDirectory = new Map();
|
|
155
|
-
for (const file of files) {
|
|
156
|
-
const bucket = byDirectory.get(file.directory) ?? [];
|
|
157
|
-
bucket.push(file);
|
|
158
|
-
byDirectory.set(file.directory, bucket);
|
|
159
|
-
}
|
|
160
|
-
return {
|
|
161
|
-
root: resolvedRoot,
|
|
162
|
-
files,
|
|
163
|
-
byDirectory,
|
|
164
|
-
filePaths: new Set(files.map((file) => file.absolutePath)),
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
export function buildSelectionContext(index, component) {
|
|
168
|
-
const absolutePath = isAbsolute(component.source) ? component.source : resolve(index.root, component.source);
|
|
169
|
-
if (!isWithinRoot(absolutePath, index.root))
|
|
170
|
-
return undefined;
|
|
171
|
-
const componentFile = index.files.find((file) => file.absolutePath === absolutePath);
|
|
172
|
-
if (!componentFile)
|
|
173
|
-
return undefined;
|
|
174
|
-
const siblings = index.byDirectory.get(componentFile.directory) ?? [];
|
|
175
|
-
return {
|
|
176
|
-
boundaryRoot: index.root,
|
|
177
|
-
componentFile: {
|
|
178
|
-
path: componentFile.relativePath,
|
|
179
|
-
code: truncateText(componentFile.text, MAX_COMPONENT_SOURCE_CHARS),
|
|
180
|
-
},
|
|
181
|
-
imports: parseImports(componentFile.text, componentFile.directory, index.root, index.filePaths),
|
|
182
|
-
exports: parseExports(componentFile.text),
|
|
183
|
-
siblingFiles: summarizeSiblingFiles(index.root, siblings, componentFile.absolutePath),
|
|
184
|
-
resolverReferences: findResolverReferences(index.root, index.files, component.name, componentFile.absolutePath),
|
|
185
|
-
parentUsageSite: findParentUsageSite(index.root, index.files, component.name, componentFile.absolutePath),
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
export function summarizeSelectionContext(context) {
|
|
189
|
-
if (!context)
|
|
190
|
-
return undefined;
|
|
191
|
-
return {
|
|
192
|
-
boundaryRoot: context.boundaryRoot,
|
|
193
|
-
siblingFileCount: context.siblingFiles.length,
|
|
194
|
-
resolverReferenceCount: context.resolverReferences.length,
|
|
195
|
-
hasParentUsageSite: Boolean(context.parentUsageSite),
|
|
196
|
-
};
|
|
197
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { openPipelineDb, findLatestSessionForCommand } from '../../session/db.js';
|
|
2
|
-
const REQUIRED_COLUMNS = ['status', 'reject_reason'];
|
|
3
|
-
function assertSchema(dbPath) {
|
|
4
|
-
const db = openPipelineDb(dbPath);
|
|
5
|
-
try {
|
|
6
|
-
const cols = db.prepare('PRAGMA table_info(raw_components)').all();
|
|
7
|
-
const have = new Set(cols.map((c) => c.name));
|
|
8
|
-
const missing = REQUIRED_COLUMNS.filter((c) => !have.has(c));
|
|
9
|
-
if (missing.length > 0) {
|
|
10
|
-
throw new Error(`Rationale data missing — run a fresh 'experiences import' on this session first. ` +
|
|
11
|
-
`(raw_components is missing column(s): ${missing.join(', ')})`);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
finally {
|
|
15
|
-
db.close();
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Resolves which session to read from. If `sessionFlag` is provided, asserts
|
|
20
|
-
* the session exists and has at least one raw component; otherwise falls back
|
|
21
|
-
* to the most recent completed `analyze select` step.
|
|
22
|
-
*/
|
|
23
|
-
export function resolveRationaleSession(sessionFlag, dbPath) {
|
|
24
|
-
const db = openPipelineDb(dbPath);
|
|
25
|
-
try {
|
|
26
|
-
if (sessionFlag) {
|
|
27
|
-
const row = db.prepare('SELECT 1 AS ok FROM raw_components WHERE session_id = ? LIMIT 1').get(sessionFlag);
|
|
28
|
-
if (!row) {
|
|
29
|
-
throw new Error(`Session not found or has no components: '${sessionFlag}'. ` +
|
|
30
|
-
`Run 'analyze extract' + 'analyze select-agent' on this session first.`);
|
|
31
|
-
}
|
|
32
|
-
return sessionFlag;
|
|
33
|
-
}
|
|
34
|
-
const latest = findLatestSessionForCommand(db, 'analyze select');
|
|
35
|
-
if (!latest) {
|
|
36
|
-
throw new Error(`No completed 'analyze select' session found. Run 'analyze select-agent' first, or pass --session <id>.`);
|
|
37
|
-
}
|
|
38
|
-
return latest;
|
|
39
|
-
}
|
|
40
|
-
finally {
|
|
41
|
-
db.close();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
export function loadRationaleRows(sessionId, dbPath) {
|
|
45
|
-
const db = openPipelineDb(dbPath);
|
|
46
|
-
try {
|
|
47
|
-
const rows = db
|
|
48
|
-
.prepare(`SELECT name, status, reject_reason FROM raw_components
|
|
49
|
-
WHERE session_id = ?
|
|
50
|
-
ORDER BY name`)
|
|
51
|
-
.all(sessionId);
|
|
52
|
-
return rows.map((r) => ({
|
|
53
|
-
name: r.name,
|
|
54
|
-
decision: r.status ?? 'extracted',
|
|
55
|
-
reason: r.reject_reason,
|
|
56
|
-
}));
|
|
57
|
-
}
|
|
58
|
-
finally {
|
|
59
|
-
db.close();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
export function formatRationaleTable(rows) {
|
|
63
|
-
if (rows.length === 0) {
|
|
64
|
-
return 'No rationale rows found for this session.\n';
|
|
65
|
-
}
|
|
66
|
-
const header = { name: 'Component', decision: 'Decision', reason: 'Reason' };
|
|
67
|
-
const all = [header, ...rows.map((r) => ({ name: r.name, decision: r.decision, reason: r.reason ?? '' }))];
|
|
68
|
-
const nameWidth = Math.max(...all.map((r) => r.name.length));
|
|
69
|
-
const decisionWidth = Math.max(...all.map((r) => r.decision.length));
|
|
70
|
-
const lines = [];
|
|
71
|
-
const fmt = (n, d, r) => `${n.padEnd(nameWidth)} ${d.padEnd(decisionWidth)} ${r}`;
|
|
72
|
-
lines.push(fmt(header.name, header.decision, header.reason));
|
|
73
|
-
lines.push(fmt('-'.repeat(nameWidth), '-'.repeat(decisionWidth), '-'.repeat(Math.max(6, header.reason.length))));
|
|
74
|
-
for (const row of rows) {
|
|
75
|
-
lines.push(fmt(row.name, row.decision, row.reason ?? ''));
|
|
76
|
-
}
|
|
77
|
-
return lines.join('\n') + '\n';
|
|
78
|
-
}
|
|
79
|
-
export function formatRationaleJson(rows) {
|
|
80
|
-
return (JSON.stringify(rows.map((r) => ({ name: r.name, decision: r.decision, reason: r.reason })), null, 2) + '\n');
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Top-level dispatch for `analyze select-agent --show-rationale`. Pure I/O
|
|
84
|
-
* boundary: reads DB, writes formatted output to stdout, throws on error.
|
|
85
|
-
*/
|
|
86
|
-
export function runShowRationale(opts) {
|
|
87
|
-
assertSchema(opts.dbPath);
|
|
88
|
-
const sessionId = resolveRationaleSession(opts.session, opts.dbPath);
|
|
89
|
-
const rows = loadRationaleRows(sessionId, opts.dbPath);
|
|
90
|
-
const output = opts.json ? formatRationaleJson(rows) : formatRationaleTable(rows);
|
|
91
|
-
process.stdout.write(output);
|
|
92
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { computeClosure } from './composite-closure.js';
|
|
2
|
-
import { findAllAncestors } from './lineage.js';
|
|
3
|
-
export function computeRejectCascade(target, components) {
|
|
4
|
-
const out = new Set();
|
|
5
|
-
out.add(target);
|
|
6
|
-
for (const ancestor of findAllAncestors(target, components)) {
|
|
7
|
-
out.add(ancestor);
|
|
8
|
-
}
|
|
9
|
-
return out;
|
|
10
|
-
}
|
|
11
|
-
export function computeAcceptCascade(target, components) {
|
|
12
|
-
const out = new Set();
|
|
13
|
-
out.add(target);
|
|
14
|
-
const closure = computeClosure(target, components);
|
|
15
|
-
for (const node of closure.nodes) {
|
|
16
|
-
out.add(node.name);
|
|
17
|
-
}
|
|
18
|
-
return out;
|
|
19
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const REJECTED_STATUSES = new Set(['error', 'rejected']);
|
|
2
|
-
export function buildComponentGraph(components, opts) {
|
|
3
|
-
const stripRejectedEdges = opts?.stripRejectedEdges === true;
|
|
4
|
-
return components.map((row) => {
|
|
5
|
-
if (stripRejectedEdges && row.status !== undefined && REJECTED_STATUSES.has(row.status)) {
|
|
6
|
-
return { name: row.key, slots: [] };
|
|
7
|
-
}
|
|
8
|
-
const slotDefs = row.entry.$slots ?? {};
|
|
9
|
-
const slots = Object.entries(slotDefs).map(([slotName, slotDef]) => ({
|
|
10
|
-
name: slotName,
|
|
11
|
-
allowedComponents: Array.isArray(slotDef?.$allowedComponents)
|
|
12
|
-
? slotDef.$allowedComponents.filter((v) => typeof v === 'string')
|
|
13
|
-
: [],
|
|
14
|
-
}));
|
|
15
|
-
return { name: row.key, slots };
|
|
16
|
-
});
|
|
17
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { Box, Text, useStdout } from 'ink';
|
|
4
|
-
import { TopBar } from '../select/tui/components/TopBar.js';
|
|
5
|
-
import { useImmediateInput } from '../select/tui/hooks/useImmediateInput.js';
|
|
6
|
-
function truncateName(name, maxLen = 30) {
|
|
7
|
-
if (name.length <= maxLen)
|
|
8
|
-
return name;
|
|
9
|
-
return name.slice(0, maxLen - 1) + '…';
|
|
10
|
-
}
|
|
11
|
-
export function AnalyzeView({ result, onExit }) {
|
|
12
|
-
const [scrollOffset, setScrollOffset] = useState(0);
|
|
13
|
-
const { stdout } = useStdout();
|
|
14
|
-
// Header lines: TopBar(1) + summary(3) + blank(1) + dividers+header(3) + blank(1) + footer(1) + footer-bar(1) = ~12
|
|
15
|
-
const HEADER_ROWS = 12;
|
|
16
|
-
const terminalRows = stdout?.rows ?? 24;
|
|
17
|
-
const visibleCount = Math.max(1, terminalRows - HEADER_ROWS);
|
|
18
|
-
const maxOffset = Math.max(0, result.components.length - visibleCount);
|
|
19
|
-
useImmediateInput((input, key) => {
|
|
20
|
-
if (input === 'q' || key.return) {
|
|
21
|
-
onExit();
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (key.upArrow || input === 'k') {
|
|
25
|
-
setScrollOffset((o) => Math.max(0, o - 1));
|
|
26
|
-
}
|
|
27
|
-
else if (key.downArrow || input === 'j') {
|
|
28
|
-
setScrollOffset((o) => Math.min(maxOffset, o + 1));
|
|
29
|
-
}
|
|
30
|
-
else if (input === 'g') {
|
|
31
|
-
setScrollOffset(0);
|
|
32
|
-
}
|
|
33
|
-
else if (input === 'G') {
|
|
34
|
-
setScrollOffset(maxOffset);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
const visible = result.components.slice(scrollOffset, scrollOffset + visibleCount);
|
|
38
|
-
const showScrollUp = scrollOffset > 0;
|
|
39
|
-
const showScrollDown = scrollOffset + visibleCount < result.components.length;
|
|
40
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(TopBar, { subcommand: "analyze", hints: [
|
|
41
|
-
{ key: '?', label: 'help' },
|
|
42
|
-
{ key: 'q', label: 'quit' },
|
|
43
|
-
] }), _jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsx(Text, { children: 'Scanned ' + result.fileCount + ' source files in ' + result.sourceDirectory }), _jsx(Text, { children: 'Extracted ' + result.components.length + ' components' }), _jsx(Text, { dimColor: true, children: 'Session: ' + result.sessionId }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, children: 'Components' +
|
|
44
|
-
(showScrollUp || showScrollDown
|
|
45
|
-
? ' (' +
|
|
46
|
-
(scrollOffset + 1) +
|
|
47
|
-
'–' +
|
|
48
|
-
Math.min(scrollOffset + visibleCount, result.components.length) +
|
|
49
|
-
' of ' +
|
|
50
|
-
result.components.length +
|
|
51
|
-
')'
|
|
52
|
-
: '') }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), showScrollUp && _jsx(Text, { dimColor: true, children: " \u25B2 scroll up" }), visible.map((component) => {
|
|
53
|
-
const conf = component.extractionConfidence;
|
|
54
|
-
const confColor = conf === null ? 'gray' : component.needsReview ? 'red' : conf >= 4 ? 'white' : conf >= 3 ? 'yellow' : 'red';
|
|
55
|
-
const confLabel = conf === null ? '—' : (component.needsReview ? '⚑ ' : '') + String(conf);
|
|
56
|
-
return (_jsxs(Box, { children: [component.errors.length > 0 && _jsx(Text, { color: "red", children: "\u2717 " }), component.errors.length === 0 && component.warnings.length > 0 && _jsx(Text, { color: "yellow", children: "\u26A0 " }), component.errors.length === 0 && component.warnings.length === 0 && _jsx(Text, { children: " " }), _jsx(Text, { children: truncateName(component.name).padEnd(20) }), _jsx(Text, { dimColor: true, children: component.framework.padEnd(10) }), _jsx(Text, { children: (component.propCount + ' props').padEnd(10) }), _jsx(Text, { children: (component.slotCount + ' ' + (component.slotCount === 1 ? 'slot' : 'slots')).padEnd(8) }), _jsx(Text, { color: confColor, children: confLabel }), component.errors.length > 0 && (_jsx(Text, { color: "red", children: ' ✗ ' + component.errors.length + ' error' + (component.errors.length === 1 ? '' : 's') })), component.errors.length === 0 && component.warnings.length > 0 && (_jsx(Text, { color: "yellow", children: ' ⚠ ' + component.warnings.length + ' warning' + (component.warnings.length === 1 ? '' : 's') }))] }, component.name));
|
|
57
|
-
}), showScrollDown && _jsx(Text, { dimColor: true, children: " \u25BC scroll down" }), result.totalErrors > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, color: "red", children: 'Errors (' + result.totalErrors + ')' }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), result.components
|
|
58
|
-
.filter((c) => c.errors.length > 0)
|
|
59
|
-
.flatMap((c) => c.errors.map((e) => ({ component: c.name, error: e })))
|
|
60
|
-
.map((e, i) => (_jsx(Text, { color: "red", children: ' ✗ ' + e.component + ': ' + e.error }, i)))] })), result.totalWarnings > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, color: "yellow", children: 'Warnings (' + result.totalWarnings + ')' }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), (result.globalWarnings ?? []).map((w, i) => (_jsx(Text, { color: "yellow", children: ' ⚠ ' + w }, `g${i}`))), result.components
|
|
61
|
-
.filter((c) => c.warnings.length > 0)
|
|
62
|
-
.flatMap((c) => c.warnings.map((w) => ({ component: c.name, warning: w })))
|
|
63
|
-
.map((w, i) => (_jsx(Text, { color: "yellow", children: ' ⚠ ' + (w.warning.startsWith(w.component + ': ') ? w.warning : w.component + ': ' + w.warning) }, `c${i}`)))] })), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: 'Run: analyze select --session ' + result.sessionId }), _jsx(Text, { children: " " })] }), _jsx(Box, { borderStyle: "single", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter or q to exit" }) })] }));
|
|
64
|
-
}
|