@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,269 +0,0 @@
|
|
|
1
|
-
const LAMBDA_LOG_PREFIX_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\s+[0-9a-f-]+\s+ERROR\s+(?:\[dd\.[^\]]*\]\s*)?/;
|
|
2
|
-
const DD_TAG_RE = /\[dd\.(?:trace_id|span_id)=[^\]]*\]\s*/g;
|
|
3
|
-
export function stripLambdaLogPrefix(body) {
|
|
4
|
-
let out = body.replace(LAMBDA_LOG_PREFIX_RE, '');
|
|
5
|
-
out = out.replace(DD_TAG_RE, '');
|
|
6
|
-
return out.trim();
|
|
7
|
-
}
|
|
8
|
-
function parseObjectLiteralTail(body) {
|
|
9
|
-
const braceStart = body.lastIndexOf('{');
|
|
10
|
-
if (braceStart === -1)
|
|
11
|
-
return null;
|
|
12
|
-
const tail = body.slice(braceStart);
|
|
13
|
-
const codeMatch = tail.match(/code:\s*['"]([^'"]+)['"]/);
|
|
14
|
-
const cycleMatch = tail.match(/cycle:\s*\[\s*([^\]]*)\s*\]/);
|
|
15
|
-
if (!codeMatch && !cycleMatch)
|
|
16
|
-
return null;
|
|
17
|
-
const code = codeMatch ? codeMatch[1] : null;
|
|
18
|
-
let cycle = null;
|
|
19
|
-
if (cycleMatch) {
|
|
20
|
-
cycle = cycleMatch[1]
|
|
21
|
-
.split(',')
|
|
22
|
-
.map((s) => s.trim().replace(/^['"]|['"]$/g, ''))
|
|
23
|
-
.filter((s) => s.length > 0);
|
|
24
|
-
if (cycle.length === 0)
|
|
25
|
-
cycle = null;
|
|
26
|
-
}
|
|
27
|
-
return { code, cycle };
|
|
28
|
-
}
|
|
29
|
-
function asRecord(value) {
|
|
30
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
31
|
-
? value
|
|
32
|
-
: null;
|
|
33
|
-
}
|
|
34
|
-
function displayValue(value) {
|
|
35
|
-
if (typeof value === 'string')
|
|
36
|
-
return value;
|
|
37
|
-
if (typeof value === 'number' || typeof value === 'boolean')
|
|
38
|
-
return String(value);
|
|
39
|
-
if (value === null || value === undefined)
|
|
40
|
-
return null;
|
|
41
|
-
try {
|
|
42
|
-
return JSON.stringify(value);
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function isPathSegment(value) {
|
|
49
|
-
return typeof value === 'string' || (typeof value === 'number' && Number.isFinite(value));
|
|
50
|
-
}
|
|
51
|
-
function formatPath(value) {
|
|
52
|
-
if (isPathSegment(value))
|
|
53
|
-
return String(value) ? { path: String(value) } : { path: null };
|
|
54
|
-
if (Array.isArray(value)) {
|
|
55
|
-
const parts = value.filter(isPathSegment);
|
|
56
|
-
return parts.length > 0 ? { path: parts.join(' › ') } : { path: null };
|
|
57
|
-
}
|
|
58
|
-
return {};
|
|
59
|
-
}
|
|
60
|
-
function componentFromPath(path) {
|
|
61
|
-
if (!path)
|
|
62
|
-
return undefined;
|
|
63
|
-
const manifestMatch = path.match(/manifest:components\/([^/›]+)/);
|
|
64
|
-
if (manifestMatch?.[1])
|
|
65
|
-
return manifestMatch[1];
|
|
66
|
-
const parts = path
|
|
67
|
-
.split(/[›/]/)
|
|
68
|
-
.map((part) => part.trim())
|
|
69
|
-
.filter(Boolean);
|
|
70
|
-
const componentsIndex = parts.findIndex((part) => part === 'components');
|
|
71
|
-
return componentsIndex === -1 ? undefined : parts[componentsIndex + 1];
|
|
72
|
-
}
|
|
73
|
-
function diagnosticMessage(error) {
|
|
74
|
-
const candidates = [
|
|
75
|
-
['message', error.message],
|
|
76
|
-
['details', error.details],
|
|
77
|
-
['error', error.error],
|
|
78
|
-
['name', error.name],
|
|
79
|
-
];
|
|
80
|
-
for (const [messageSource, value] of candidates) {
|
|
81
|
-
const message = displayValue(value);
|
|
82
|
-
if (message !== null)
|
|
83
|
-
return { message, messageSource };
|
|
84
|
-
}
|
|
85
|
-
return { message: 'Validation failed' };
|
|
86
|
-
}
|
|
87
|
-
function parseValidationDiagnostics(details) {
|
|
88
|
-
if (!Array.isArray(details.errors))
|
|
89
|
-
return [];
|
|
90
|
-
const diagnostics = [];
|
|
91
|
-
for (const rawError of details.errors) {
|
|
92
|
-
const error = asRecord(rawError);
|
|
93
|
-
if (!error)
|
|
94
|
-
continue;
|
|
95
|
-
const location = formatPath(error.path);
|
|
96
|
-
const component = displayValue(error.component ?? error.componentName ?? error.componentId) ?? componentFromPath(location.path);
|
|
97
|
-
diagnostics.push({ ...diagnosticMessage(error), ...location, ...(component ? { component } : {}) });
|
|
98
|
-
}
|
|
99
|
-
return diagnostics;
|
|
100
|
-
}
|
|
101
|
-
function parseJsonBody(body) {
|
|
102
|
-
let parsed;
|
|
103
|
-
try {
|
|
104
|
-
parsed = JSON.parse(body);
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
const p = asRecord(parsed);
|
|
110
|
-
if (!p)
|
|
111
|
-
return null;
|
|
112
|
-
const details = asRecord(p.details) ?? {};
|
|
113
|
-
const pick = (k) => (p[k] !== undefined ? p[k] : details[k]);
|
|
114
|
-
const codeRaw = pick('code') ?? asRecord(p.sys)?.id;
|
|
115
|
-
const messageRaw = pick('message');
|
|
116
|
-
const cycleRaw = pick('cycle');
|
|
117
|
-
const out = {};
|
|
118
|
-
if (typeof codeRaw === 'string')
|
|
119
|
-
out.code = codeRaw;
|
|
120
|
-
if (typeof messageRaw === 'string')
|
|
121
|
-
out.message = messageRaw;
|
|
122
|
-
if (Array.isArray(cycleRaw)) {
|
|
123
|
-
const strs = cycleRaw.filter((x) => typeof x === 'string');
|
|
124
|
-
if (strs.length > 0)
|
|
125
|
-
out.cycle = strs;
|
|
126
|
-
}
|
|
127
|
-
const diagnostics = parseValidationDiagnostics(details);
|
|
128
|
-
if (diagnostics.length > 0)
|
|
129
|
-
out.diagnostics = diagnostics;
|
|
130
|
-
return out;
|
|
131
|
-
}
|
|
132
|
-
function parseBindingDiagnostics(body) {
|
|
133
|
-
if (!/binding configurations are invalid|Pointer path does not exist/i.test(body))
|
|
134
|
-
return null;
|
|
135
|
-
const locationMatches = [...body.matchAll(/(?:^|\.\s)([A-Za-z0-9_$-]+(?:\s*›\s*[A-Za-z0-9_$-]+){2,})/g)];
|
|
136
|
-
const location = locationMatches.at(-1)?.[1];
|
|
137
|
-
const pointerMessage = body.match(/Pointer path does not exist for '\[object Object\]':\s*(.+?)(?=\.\s*Default\s*›|$)/i)?.[1];
|
|
138
|
-
const graphQlMessage = body.match(/return GraphQL validation error:\s*(.+?)(?=\.\s*Default\s*›|$)/i)?.[1];
|
|
139
|
-
const heading = body.match(/^(.*?)(?=\.?\s*Pointer path does not exist|\.?\s*Default\s*›)/i)?.[1]?.trim();
|
|
140
|
-
const diagnostics = [];
|
|
141
|
-
if (pointerMessage)
|
|
142
|
-
diagnostics.push({ message: pointerMessage.trim(), ...(location ? { path: location } : {}) });
|
|
143
|
-
if (graphQlMessage)
|
|
144
|
-
diagnostics.push({ message: graphQlMessage.trim(), ...(location ? { path: location } : {}) });
|
|
145
|
-
return {
|
|
146
|
-
code: 'BindingValidationFailed',
|
|
147
|
-
message: heading || 'One or more binding configurations are invalid.',
|
|
148
|
-
...(diagnostics.length > 0 ? { diagnostics } : {}),
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
// ApiError.message shape: `${phasePrefix}\n${body}` where phasePrefix looks
|
|
152
|
-
// like `apply failed: 400`, `preview failed: 422`, `poll failed: 500`. We
|
|
153
|
-
// only strip the prefix line when the first line matches this shape —
|
|
154
|
-
// otherwise a raw body that happens to contain a newline (e.g. a Lambda log
|
|
155
|
-
// spill with a multi-line object literal) gets truncated mid-structure.
|
|
156
|
-
const API_ERROR_PREFIX_RE = /^(?:apply|preview|poll) failed: \d+$/;
|
|
157
|
-
export function parseEdsiError(rawInput) {
|
|
158
|
-
if (!rawInput)
|
|
159
|
-
return { code: null, message: '', cycle: null, raw: true };
|
|
160
|
-
const nlIndex = rawInput.indexOf('\n');
|
|
161
|
-
let body = rawInput;
|
|
162
|
-
let prefix = '';
|
|
163
|
-
if (nlIndex !== -1) {
|
|
164
|
-
const firstLine = rawInput.slice(0, nlIndex);
|
|
165
|
-
if (API_ERROR_PREFIX_RE.test(firstLine)) {
|
|
166
|
-
prefix = firstLine;
|
|
167
|
-
body = rawInput.slice(nlIndex + 1);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
const cleaned = stripLambdaLogPrefix(body);
|
|
171
|
-
const json = parseJsonBody(cleaned) ?? parseJsonBody(body);
|
|
172
|
-
const bindingFromJson = typeof json?.message === 'string' ? parseBindingDiagnostics(json.message) : null;
|
|
173
|
-
if (bindingFromJson) {
|
|
174
|
-
return {
|
|
175
|
-
code: bindingFromJson.code ?? json?.code ?? null,
|
|
176
|
-
message: bindingFromJson.message ?? cleaned,
|
|
177
|
-
cycle: null,
|
|
178
|
-
raw: false,
|
|
179
|
-
...(bindingFromJson.diagnostics ? { diagnostics: bindingFromJson.diagnostics } : {}),
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
if (json && (json.code || json.message || json.cycle)) {
|
|
183
|
-
return {
|
|
184
|
-
code: json.code ?? null,
|
|
185
|
-
message: json.message ?? (cleaned || prefix),
|
|
186
|
-
cycle: json.cycle ?? null,
|
|
187
|
-
raw: false,
|
|
188
|
-
...(json.diagnostics ? { diagnostics: json.diagnostics } : {}),
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
const binding = parseBindingDiagnostics(cleaned);
|
|
192
|
-
if (binding) {
|
|
193
|
-
return {
|
|
194
|
-
code: binding.code ?? null,
|
|
195
|
-
message: binding.message ?? cleaned,
|
|
196
|
-
cycle: null,
|
|
197
|
-
raw: false,
|
|
198
|
-
...(binding.diagnostics ? { diagnostics: binding.diagnostics } : {}),
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
const literal = parseObjectLiteralTail(cleaned);
|
|
202
|
-
if (literal && (literal.code || literal.cycle)) {
|
|
203
|
-
const braceStart = cleaned.lastIndexOf('{');
|
|
204
|
-
const head = braceStart === -1 ? cleaned : cleaned.slice(0, braceStart).trim();
|
|
205
|
-
return {
|
|
206
|
-
code: literal.code ?? null,
|
|
207
|
-
message: head || cleaned,
|
|
208
|
-
cycle: literal.cycle ?? null,
|
|
209
|
-
raw: false,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
return { code: null, message: cleaned || prefix || rawInput, cycle: null, raw: true };
|
|
213
|
-
}
|
|
214
|
-
export function formatParsedEdsiError(parsed, opts = {}) {
|
|
215
|
-
const lines = [];
|
|
216
|
-
if (parsed.code) {
|
|
217
|
-
lines.push(`[${parsed.code}]`);
|
|
218
|
-
}
|
|
219
|
-
if (parsed.message) {
|
|
220
|
-
lines.push(parsed.message);
|
|
221
|
-
}
|
|
222
|
-
for (const diagnostic of parsed.diagnostics ?? []) {
|
|
223
|
-
const context = [
|
|
224
|
-
diagnostic.component ? `Component: ${diagnostic.component}` : null,
|
|
225
|
-
diagnostic.path ? `Path: ${diagnostic.path}` : null,
|
|
226
|
-
].filter(Boolean);
|
|
227
|
-
lines.push(`- ${diagnostic.message}${context.length > 0 ? ` (${context.join('; ')})` : ''}`);
|
|
228
|
-
if (diagnostic.path === null) {
|
|
229
|
-
lines.push(' Location: not provided by the server. Review the submitted manifest; no component or field was identified.');
|
|
230
|
-
}
|
|
231
|
-
if (opts.verbose && diagnostic.messageSource) {
|
|
232
|
-
lines.push(` Message field: ${diagnostic.messageSource}`);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (parsed.code === 'BindingValidationFailed') {
|
|
236
|
-
const location = parsed.diagnostics?.find((diagnostic) => diagnostic.path)?.path;
|
|
237
|
-
lines.push(location
|
|
238
|
-
? `Next action: review the binding at ${location} and correct its pointer or GraphQL selection.`
|
|
239
|
-
: 'Next action: review the binding pointer and GraphQL selection.');
|
|
240
|
-
}
|
|
241
|
-
if (parsed.code === 'AccessDenied') {
|
|
242
|
-
lines.push('Next action: this operation requires DesignToken and Component permissions in this environment. Ask a Contentful admin to grant both on your role.');
|
|
243
|
-
}
|
|
244
|
-
if (parsed.code === 'NotFound') {
|
|
245
|
-
lines.push('Next action: verify the resource id is correct. If it should exist, your role may lack read permission on DesignToken or Component.');
|
|
246
|
-
}
|
|
247
|
-
if (parsed.cycle && parsed.cycle.length > 0) {
|
|
248
|
-
lines.push(`Cycle: ${parsed.cycle.join(' → ')} → ${parsed.cycle[0]}`);
|
|
249
|
-
lines.push('Break the cycle by removing at least one $allowedComponents entry.');
|
|
250
|
-
}
|
|
251
|
-
if (opts.verbose && opts.raw) {
|
|
252
|
-
lines.push('');
|
|
253
|
-
lines.push('--- raw ---');
|
|
254
|
-
lines.push(opts.raw);
|
|
255
|
-
}
|
|
256
|
-
return lines.filter(Boolean).join('\n');
|
|
257
|
-
}
|
|
258
|
-
export function formatEdsiError(raw, opts = {}) {
|
|
259
|
-
const input = typeof raw === 'string' ? raw : displayValue(raw);
|
|
260
|
-
if (!input)
|
|
261
|
-
return '';
|
|
262
|
-
return formatParsedEdsiError(parseEdsiError(input), { ...opts, raw: opts.raw ?? input });
|
|
263
|
-
}
|
|
264
|
-
export function formatApiError(error, verbose = false) {
|
|
265
|
-
const formatted = formatEdsiError(error.body || error.message, { verbose, raw: error.body }) || error.message;
|
|
266
|
-
const phase = error.message.split('\n', 1)[0];
|
|
267
|
-
const withPhase = /^(?:apply|preview|poll) failed: \d+$/.test(phase) && formatted !== phase ? `${phase}\n${formatted}` : formatted;
|
|
268
|
-
return error.guidance ? `${withPhase}\n${error.guidance}` : withPhase;
|
|
269
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic `--prompt <stage>=<value>` override parser.
|
|
3
|
-
*
|
|
4
|
-
* One repeatable flag overrides the prompt for any named pipeline stage
|
|
5
|
-
* (e.g. `composition`, `select`, `generate`). The value is classified by
|
|
6
|
-
* string SHAPE only — no filesystem access here: a value that looks like a
|
|
7
|
-
* path is resolved+read by the consumer; otherwise it is treated as the
|
|
8
|
-
* literal prompt text. This keeps the parser pure and testable.
|
|
9
|
-
*/
|
|
10
|
-
import { readFile } from 'node:fs/promises';
|
|
11
|
-
import { resolve } from 'node:path';
|
|
12
|
-
const PROMPT_FILE_EXTENSIONS = ['.md', '.txt', '.prompt'];
|
|
13
|
-
/**
|
|
14
|
-
* Heuristic: does this value look like a file path (vs. literal prompt text)?
|
|
15
|
-
* Path if it contains a path separator, starts with `~`, or ends with a known
|
|
16
|
-
* prompt-file extension. Deliberately does NOT touch the filesystem.
|
|
17
|
-
*/
|
|
18
|
-
export function looksLikePath(value) {
|
|
19
|
-
if (value.includes('/') || value.includes('\\'))
|
|
20
|
-
return true;
|
|
21
|
-
if (value.startsWith('~'))
|
|
22
|
-
return true;
|
|
23
|
-
const lower = value.toLowerCase();
|
|
24
|
-
return PROMPT_FILE_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Parse repeated `stage=value` flag inputs into a stage→override map. Splits on
|
|
28
|
-
* the FIRST `=` so values may contain `=`. Last write wins for a repeated
|
|
29
|
-
* stage. Malformed entries are collected in `errors` (caller decides fatality).
|
|
30
|
-
*/
|
|
31
|
-
export function parsePromptOverrides(inputs) {
|
|
32
|
-
const overrides = new Map();
|
|
33
|
-
const errors = [];
|
|
34
|
-
for (const raw of inputs) {
|
|
35
|
-
const eq = raw.indexOf('=');
|
|
36
|
-
if (eq === -1) {
|
|
37
|
-
errors.push(`--prompt "${raw}" must be in the form stage=value`);
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
const stage = raw.slice(0, eq).trim();
|
|
41
|
-
const value = raw.slice(eq + 1);
|
|
42
|
-
if (stage === '') {
|
|
43
|
-
errors.push(`--prompt "${raw}" has an empty stage (expected stage=value)`);
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
if (value === '') {
|
|
47
|
-
errors.push(`--prompt "${raw}" has an empty value`);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
overrides.set(stage, looksLikePath(value) ? { kind: 'path', value } : { kind: 'text', value });
|
|
51
|
-
}
|
|
52
|
-
return { overrides, errors };
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Resolve an override to its prompt text: read the file for a `path` override
|
|
56
|
-
* (resolved against cwd), or return the literal `text` value. Throws with a
|
|
57
|
-
* clear message if a path override can't be read.
|
|
58
|
-
*/
|
|
59
|
-
export async function resolvePromptOverride(override) {
|
|
60
|
-
if (override.kind === 'text')
|
|
61
|
-
return override.value;
|
|
62
|
-
const abs = resolve(override.value);
|
|
63
|
-
try {
|
|
64
|
-
return await readFile(abs, 'utf8');
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
throw new Error(`--prompt: could not read prompt file: ${abs}`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Check the capabilities Ink's interactive input hooks require before the UI
|
|
3
|
-
* mounts. A stream can report itself as a TTY while its terminal host still
|
|
4
|
-
* rejects raw mode, so the check briefly enables and restores raw mode.
|
|
5
|
-
*/
|
|
6
|
-
export function getInteractiveTerminalSupport(options = {}) {
|
|
7
|
-
const stdin = options.stdin ?? process.stdin;
|
|
8
|
-
const stdout = options.stdout ?? process.stdout;
|
|
9
|
-
if (stdout.isTTY !== true)
|
|
10
|
-
return { supported: false, reason: 'output-not-tty' };
|
|
11
|
-
if (stdin.isTTY !== true)
|
|
12
|
-
return { supported: false, reason: 'input-not-tty' };
|
|
13
|
-
if (typeof stdin.setRawMode !== 'function') {
|
|
14
|
-
return { supported: false, reason: 'raw-mode-unavailable' };
|
|
15
|
-
}
|
|
16
|
-
const wasRaw = stdin.isRaw === true;
|
|
17
|
-
try {
|
|
18
|
-
stdin.setRawMode(true);
|
|
19
|
-
if (!wasRaw)
|
|
20
|
-
stdin.setRawMode(false);
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
if (!wasRaw) {
|
|
24
|
-
try {
|
|
25
|
-
stdin.setRawMode(false);
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
// The original capability failure is the actionable result.
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return { supported: false, reason: 'raw-mode-unavailable' };
|
|
32
|
-
}
|
|
33
|
-
return { supported: true };
|
|
34
|
-
}
|
|
35
|
-
export function requireInteractiveTerminal(options = {}) {
|
|
36
|
-
const support = getInteractiveTerminalSupport(options);
|
|
37
|
-
if (support.supported)
|
|
38
|
-
return;
|
|
39
|
-
const reason = support.reason === 'output-not-tty'
|
|
40
|
-
? 'standard output is not a TTY'
|
|
41
|
-
: support.reason === 'input-not-tty'
|
|
42
|
-
? 'standard input is not a TTY'
|
|
43
|
-
: 'standard input cannot enter raw mode';
|
|
44
|
-
const lines = [
|
|
45
|
-
`Interactive terminal UI is unavailable because ${reason}.`,
|
|
46
|
-
'On Windows, run this command in Windows Terminal with PowerShell.',
|
|
47
|
-
];
|
|
48
|
-
if (options.alternative)
|
|
49
|
-
lines.push(`To continue without the UI, ${options.alternative}.`);
|
|
50
|
-
throw new Error(lines.join('\n'));
|
|
51
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { createRequire } from 'node:module';
|
|
2
|
-
const require = createRequire(import.meta.url);
|
|
3
|
-
const pkg = require('../../package.json');
|
|
4
|
-
const APP = 'contentful.experience-design-system-cli';
|
|
5
|
-
// process.platform → CEP-0056 os name, mirroring contentful-sdk-core's
|
|
6
|
-
// getNodeOS so the header parses identically to SDK-originated traffic.
|
|
7
|
-
const OS_NAMES = {
|
|
8
|
-
android: 'Android',
|
|
9
|
-
aix: 'Linux',
|
|
10
|
-
darwin: 'macOS',
|
|
11
|
-
freebsd: 'Linux',
|
|
12
|
-
linux: 'Linux',
|
|
13
|
-
openbsd: 'Linux',
|
|
14
|
-
sunos: 'Linux',
|
|
15
|
-
win32: 'Windows',
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* X-Contentful-User-Agent for the CLI's CMA requests, so writes are
|
|
19
|
-
* attributable to the DSI CLI as their origin. Format follows CEP-0056:
|
|
20
|
-
* `app <name>/<ver>; platform node.js/<ver>; os <name>/<ver>;`. Carries only
|
|
21
|
-
* the app/platform/os segments — no user- or content-identifying data.
|
|
22
|
-
*/
|
|
23
|
-
export function buildUserAgent(version = pkg.version) {
|
|
24
|
-
const parts = [`app ${APP}/${version}`, `platform node.js/${process.version}`];
|
|
25
|
-
const os = OS_NAMES[process.platform];
|
|
26
|
-
if (os)
|
|
27
|
-
parts.push(`os ${os}/${process.version}`);
|
|
28
|
-
return `${parts.join('; ')};`;
|
|
29
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// Color support — checked once at module load.
|
|
2
|
-
// Honors NO_COLOR (https://no-color.org) and FORCE_COLOR (set by orchestrator for non-TTY subprocesses).
|
|
3
|
-
function detectColors() {
|
|
4
|
-
if (process.env['NO_COLOR'] !== undefined)
|
|
5
|
-
return false;
|
|
6
|
-
if (process.env['FORCE_COLOR'] !== undefined)
|
|
7
|
-
return true;
|
|
8
|
-
return process.stderr.isTTY === true;
|
|
9
|
-
}
|
|
10
|
-
const col = detectColors();
|
|
11
|
-
export const c = {
|
|
12
|
-
green: (s) => (col ? `\x1b[32m${s}\x1b[0m` : s),
|
|
13
|
-
red: (s) => (col ? `\x1b[31m${s}\x1b[0m` : s),
|
|
14
|
-
cyan: (s) => (col ? `\x1b[36m${s}\x1b[0m` : s),
|
|
15
|
-
yellow: (s) => (col ? `\x1b[33m${s}\x1b[0m` : s),
|
|
16
|
-
dim: (s) => (col ? `\x1b[2m${s}\x1b[0m` : s),
|
|
17
|
-
bold: (s) => (col ? `\x1b[1m${s}\x1b[0m` : s),
|
|
18
|
-
};
|
|
19
|
-
// Formats a single parsed tool-call object into a human-readable line, or returns null to suppress it.
|
|
20
|
-
function formatToolCall(obj) {
|
|
21
|
-
switch (obj['tool']) {
|
|
22
|
-
case 'classify_component': {
|
|
23
|
-
const desc = typeof obj['description'] === 'string' ? obj['description'] : null;
|
|
24
|
-
return desc ? ` ${c.dim('→')} ${c.dim(desc)}` : null;
|
|
25
|
-
}
|
|
26
|
-
case 'classify_prop': {
|
|
27
|
-
const prop = String(obj['prop'] ?? '');
|
|
28
|
-
const type = String(obj['cdf_type'] ?? '');
|
|
29
|
-
const cat = String(obj['cdf_category'] ?? '');
|
|
30
|
-
return ` ${c.green('+')} ${prop} ${c.dim(`${type} ${cat}`)}`;
|
|
31
|
-
}
|
|
32
|
-
case 'exclude_prop': {
|
|
33
|
-
const prop = String(obj['prop'] ?? '');
|
|
34
|
-
const reason = typeof obj['reason'] === 'string' ? obj['reason'] : '';
|
|
35
|
-
return ` ${c.dim('–')} ${prop} ${c.dim(reason)}`;
|
|
36
|
-
}
|
|
37
|
-
case 'classify_slot': {
|
|
38
|
-
const slot = String(obj['slot'] ?? '');
|
|
39
|
-
const desc = typeof obj['description'] === 'string' ? obj['description'] : '';
|
|
40
|
-
const req = obj['required'] === true ? c.dim(' required') : '';
|
|
41
|
-
return ` ${c.cyan('◈')} ${slot}${req} ${c.dim(desc)}`;
|
|
42
|
-
}
|
|
43
|
-
case 'select_component': {
|
|
44
|
-
const name = String(obj['name'] ?? '');
|
|
45
|
-
const reason = typeof obj['reason'] === 'string' ? obj['reason'] : '';
|
|
46
|
-
return ` ${c.green('+')} ${name} ${c.dim(reason)}`;
|
|
47
|
-
}
|
|
48
|
-
case 'reject_component': {
|
|
49
|
-
const name = String(obj['name'] ?? '');
|
|
50
|
-
const reason = typeof obj['reason'] === 'string' ? obj['reason'] : '';
|
|
51
|
-
return ` ${c.dim('–')} ${name} ${c.dim(reason)}`;
|
|
52
|
-
}
|
|
53
|
-
default:
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Processes streaming agent output line by line.
|
|
59
|
-
*
|
|
60
|
-
* Tool-call JSON lines are translated into human-readable summaries.
|
|
61
|
-
* Prose (reasoning text) is shown only when verbose=true.
|
|
62
|
-
*/
|
|
63
|
-
export class OutputFormatter {
|
|
64
|
-
_buf = '';
|
|
65
|
-
_verbose;
|
|
66
|
-
_write;
|
|
67
|
-
constructor(verbose, write = (s) => process.stderr.write(s)) {
|
|
68
|
-
this._verbose = verbose;
|
|
69
|
-
this._write = write;
|
|
70
|
-
}
|
|
71
|
-
push(chunk) {
|
|
72
|
-
this._buf += chunk;
|
|
73
|
-
// Process all complete lines; keep any trailing partial line in the buffer.
|
|
74
|
-
const nl = this._buf.lastIndexOf('\n');
|
|
75
|
-
if (nl === -1)
|
|
76
|
-
return;
|
|
77
|
-
const complete = this._buf.slice(0, nl + 1);
|
|
78
|
-
this._buf = this._buf.slice(nl + 1);
|
|
79
|
-
for (const line of complete.split('\n')) {
|
|
80
|
-
this._processLine(line);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
flush() {
|
|
84
|
-
if (this._buf.trim())
|
|
85
|
-
this._processLine(this._buf);
|
|
86
|
-
this._buf = '';
|
|
87
|
-
}
|
|
88
|
-
_processLine(line) {
|
|
89
|
-
const trimmed = line.trim();
|
|
90
|
-
if (!trimmed)
|
|
91
|
-
return;
|
|
92
|
-
if (trimmed.startsWith('{')) {
|
|
93
|
-
try {
|
|
94
|
-
const obj = JSON.parse(trimmed);
|
|
95
|
-
if (typeof obj['tool'] === 'string') {
|
|
96
|
-
const formatted = formatToolCall(obj);
|
|
97
|
-
if (formatted !== null)
|
|
98
|
-
this._write(formatted + '\n');
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
// not JSON — fall through to prose handling
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (this._verbose) {
|
|
107
|
-
this._write(c.dim(' ' + trimmed) + '\n');
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|