@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,127 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
const SAFE_PATH_RE = /^[a-zA-Z0-9_.$[\]=]+$/;
|
|
4
|
-
const PROTO_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
5
|
-
function applyDotPath(obj, path, value) {
|
|
6
|
-
if (!SAFE_PATH_RE.test(path)) {
|
|
7
|
-
process.stderr.write(`Warning: --patch path contains invalid characters: '${path}', skipping\n`);
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
const parts = path.split('.');
|
|
11
|
-
if (parts.some((p) => PROTO_KEYS.has(p))) {
|
|
12
|
-
process.stderr.write(`Warning: --patch path contains forbidden key: '${path}', skipping\n`);
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
let current = obj;
|
|
16
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
17
|
-
const part = parts[i];
|
|
18
|
-
const arrayMatch = /^(.+)\[name=(.+)\]$/.exec(part);
|
|
19
|
-
if (arrayMatch) {
|
|
20
|
-
const [, fieldName, matchValue] = arrayMatch;
|
|
21
|
-
const arr = current[fieldName];
|
|
22
|
-
if (Array.isArray(arr)) {
|
|
23
|
-
const item = arr.find((el) => el['name'] === matchValue);
|
|
24
|
-
if (item) {
|
|
25
|
-
current = item;
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
process.stderr.write(`Warning: --patch array item [name=${matchValue}] not found in '${fieldName}', skipping\n`);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
if (typeof current[part] !== 'object' || current[part] === null) {
|
|
35
|
-
process.stderr.write(`Warning: --patch path '${path}' — '${part}' is not an object, skipping\n`);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
current = current[part];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const lastPart = parts[parts.length - 1];
|
|
42
|
-
current[lastPart] = value;
|
|
43
|
-
}
|
|
44
|
-
function applyPatch(components, ops) {
|
|
45
|
-
return components.map((c) => {
|
|
46
|
-
const op = ops.find((o) => o.component === c.name);
|
|
47
|
-
if (!op)
|
|
48
|
-
return c;
|
|
49
|
-
let updated = { ...c };
|
|
50
|
-
if (op.status) {
|
|
51
|
-
updated = { ...updated, status: op.status };
|
|
52
|
-
}
|
|
53
|
-
if (op.set) {
|
|
54
|
-
const clone = structuredClone(updated);
|
|
55
|
-
for (const [path, value] of Object.entries(op.set)) {
|
|
56
|
-
applyDotPath(clone, path, value);
|
|
57
|
-
}
|
|
58
|
-
updated = clone;
|
|
59
|
-
}
|
|
60
|
-
return updated;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
async function loadComponentsFromSession(_sessionId, _skill) {
|
|
64
|
-
// TODO: read from pipeline.db session when the unified session layer ships
|
|
65
|
-
// For now return empty list; non-interactive flags operate on whatever is in the DB
|
|
66
|
-
process.stderr.write('Error: generate edit requires a session database (not yet implemented — coming in the next release)\n');
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
async function runNonInteractive(opts, skill) {
|
|
70
|
-
let components = await loadComponentsFromSession(opts.session, skill);
|
|
71
|
-
if (opts.acceptAll || (opts.reject ?? []).length > 0) {
|
|
72
|
-
const rejectPatterns = (opts.reject ?? []).map((p) => p.toLowerCase());
|
|
73
|
-
components = components.map((c) => {
|
|
74
|
-
const rejected = rejectPatterns.some((p) => c.name.toLowerCase().includes(p));
|
|
75
|
-
return { ...c, status: rejected ? 'rejected' : 'accepted' };
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
if (opts.patch) {
|
|
79
|
-
let patchOps;
|
|
80
|
-
try {
|
|
81
|
-
const raw = await readFile(resolve(opts.patch), 'utf8');
|
|
82
|
-
patchOps = JSON.parse(raw);
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
process.stderr.write(`Error: cannot read or parse --patch file: ${opts.patch}\n`);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const knownNames = new Set(components.map((c) => c.name));
|
|
90
|
-
for (const op of patchOps) {
|
|
91
|
-
if (!knownNames.has(op.component)) {
|
|
92
|
-
process.stderr.write(`Warning: --patch targets unknown component '${op.component}', skipping\n`);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
components = applyPatch(components, patchOps);
|
|
96
|
-
}
|
|
97
|
-
const accepted = components.filter((c) => c.status === 'accepted');
|
|
98
|
-
const rejected = components.filter((c) => c.status === 'rejected');
|
|
99
|
-
process.stderr.write(`Accepted: ${accepted.length} Rejected: ${rejected.length}\n`);
|
|
100
|
-
}
|
|
101
|
-
export function registerGenerateEditCommand(parent, skill) {
|
|
102
|
-
// TODO(analytics): bindAnalyticsSessionId when generate edit ships — tracked in schema as generate_edit.
|
|
103
|
-
parent
|
|
104
|
-
.command('edit')
|
|
105
|
-
.description(`Review and correct generate ${skill} output before pushing`)
|
|
106
|
-
.option('--session <id>', 'Session ID to operate on (defaults to most recent active session)')
|
|
107
|
-
.option('--accept-all', 'Accept all definitions without launching the TUI')
|
|
108
|
-
.option('--reject <pattern>', 'Reject definitions whose name contains pattern (repeatable)', collect, [])
|
|
109
|
-
.option('--patch <path>', 'Path to a JSON patch file for structured definition overrides')
|
|
110
|
-
.action(async ({ session, acceptAll, reject, patch }) => {
|
|
111
|
-
const nonInteractive = acceptAll || (reject ?? []).length > 0 || !!patch;
|
|
112
|
-
if (nonInteractive) {
|
|
113
|
-
await runNonInteractive({ session, acceptAll, reject, patch }, skill);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (!process.stdout.isTTY) {
|
|
117
|
-
process.stderr.write(`Error: generate ${skill} edit requires an interactive terminal\n`);
|
|
118
|
-
process.exit(1);
|
|
119
|
-
}
|
|
120
|
-
// TUI not yet implemented
|
|
121
|
-
process.stderr.write(`Error: interactive generate ${skill} edit TUI is not yet available. Use --accept-all, --reject, or --patch for non-interactive mode.\n`);
|
|
122
|
-
process.exit(1);
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
function collect(val, prev) {
|
|
126
|
-
return [...prev, val];
|
|
127
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { Box, Text } from 'ink';
|
|
4
|
-
export function GenerateView({ result, onExit }) {
|
|
5
|
-
React.useEffect(() => {
|
|
6
|
-
const timer = setTimeout(onExit, 100);
|
|
7
|
-
return () => clearTimeout(timer);
|
|
8
|
-
}, [onExit]);
|
|
9
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "green", children: "\u2713 generate complete" }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "skill " }), _jsx(Text, { children: result.skill })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "agent " }), _jsx(Text, { children: result.agent })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "session " }), _jsx(Text, { children: result.sessionId })] })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "Run " }), _jsxs(Text, { children: ["experience-design-system-cli print ", result.skill] }), _jsx(Text, { dimColor: true, children: " to write the output file." })] })] }));
|
|
10
|
-
}
|
package/dist/src/host-utils.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_API_HOST = 'https://api.contentful.com';
|
|
2
|
-
export const DEFAULT_CONFIGURED_HOST = 'api.contentful.com';
|
|
3
|
-
function trimTrailingSlashes(value) {
|
|
4
|
-
return value.replace(/\/+$/, '');
|
|
5
|
-
}
|
|
6
|
-
function normalizeHostInput(host) {
|
|
7
|
-
const value = host?.trim();
|
|
8
|
-
if (!value)
|
|
9
|
-
return undefined;
|
|
10
|
-
return trimTrailingSlashes(value);
|
|
11
|
-
}
|
|
12
|
-
export function toConfiguredHost(host) {
|
|
13
|
-
const normalized = normalizeHostInput(host);
|
|
14
|
-
if (!normalized)
|
|
15
|
-
return undefined;
|
|
16
|
-
return normalized.replace(/^https:\/\//i, '');
|
|
17
|
-
}
|
|
18
|
-
export function toApiHost(host) {
|
|
19
|
-
const normalized = normalizeHostInput(host);
|
|
20
|
-
if (!normalized)
|
|
21
|
-
return DEFAULT_API_HOST;
|
|
22
|
-
if (/^[a-z][a-z\d+\-.]*:\/\//i.test(normalized)) {
|
|
23
|
-
return normalized;
|
|
24
|
-
}
|
|
25
|
-
return `https://${normalized}`;
|
|
26
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolution chain for `--agent` and `--model` overrides on `experiences import`.
|
|
3
|
-
*
|
|
4
|
-
* The wizard path previously hard-defaulted `--agent` to `'claude'` at the
|
|
5
|
-
* commander layer, which (a) shadowed the stored `credentials.json` value when
|
|
6
|
-
* the user passed no flag, and (b) made it impossible to distinguish "user
|
|
7
|
-
* explicitly passed --agent claude" from "user passed nothing". `--model` was
|
|
8
|
-
* registered but never threaded into the wizard subprocesses at all.
|
|
9
|
-
*
|
|
10
|
-
* These helpers produce the resolved values to feed into `WizardApp` /
|
|
11
|
-
* `runPipeline`:
|
|
12
|
-
*
|
|
13
|
-
* 1. CLI flag wins when provided.
|
|
14
|
-
* 2. Otherwise, the value persisted in `credentials.json` (written by
|
|
15
|
-
* `experiences setup`) is used.
|
|
16
|
-
* 3. Otherwise, the built-in default (currently `'claude'`) is used for
|
|
17
|
-
* the agent. Model has no default — agents pick a small/fast model
|
|
18
|
-
* themselves when `--model` is omitted.
|
|
19
|
-
*/
|
|
20
|
-
/** Built-in fallback agent when neither a flag nor a stored preference is set. */
|
|
21
|
-
export const DEFAULT_AGENT = 'claude';
|
|
22
|
-
export function resolveAgent(flagValue, storedValue) {
|
|
23
|
-
if (flagValue && flagValue.length > 0)
|
|
24
|
-
return flagValue;
|
|
25
|
-
if (storedValue && storedValue.length > 0)
|
|
26
|
-
return storedValue;
|
|
27
|
-
return DEFAULT_AGENT;
|
|
28
|
-
}
|
|
29
|
-
export function resolveModel(flagValue, storedValue) {
|
|
30
|
-
if (flagValue && flagValue.length > 0)
|
|
31
|
-
return flagValue;
|
|
32
|
-
if (storedValue && storedValue.length > 0)
|
|
33
|
-
return storedValue;
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve the effective auto-filter setting from a CLI flag plus the persisted
|
|
3
|
-
* config preference.
|
|
4
|
-
*
|
|
5
|
-
* Precedence (highest first):
|
|
6
|
-
* 1. CLI flag (`--auto-filter` or `--no-auto-filter`) — wins when set
|
|
7
|
-
* 2. Config (`credentials.json` `autoFilter` field) — used when flag absent
|
|
8
|
-
* 3. Default ON — when neither is set
|
|
9
|
-
*/
|
|
10
|
-
import { getDebugLogger } from '../lib/debug-logger.js';
|
|
11
|
-
export function resolveAutoFilter(opts, configAutoFilter) {
|
|
12
|
-
const source = opts.autoFilter !== undefined ? 'flag' : configAutoFilter !== undefined ? 'config' : 'default';
|
|
13
|
-
const value = opts.autoFilter ?? configAutoFilter ?? true;
|
|
14
|
-
getDebugLogger().event('filter', 'auto-filter.resolve', { source, value });
|
|
15
|
-
return value;
|
|
16
|
-
}
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import { resolve, join } from 'node:path';
|
|
2
|
-
import { runPipeline } from './orchestrator.js';
|
|
3
|
-
import { resolveAutoFilter } from './auto-filter-resolve.js';
|
|
4
|
-
import { resolveAgent, resolveModel } from './agent-model-resolve.js';
|
|
5
|
-
import { addAgentModelOptions } from '../lib/agent-model-options.js';
|
|
6
|
-
import { resolveCompositionMode } from '../lib/composition-mode.js';
|
|
7
|
-
import { addAllowDeletionsOption, addCompositionOptions } from '../lib/command-options.js';
|
|
8
|
-
import { isConflictMode } from '../runs/save-path-resolver.js';
|
|
9
|
-
import { readExperiencesCredentials } from '../credentials-store.js';
|
|
10
|
-
import { DEFAULT_CONFIGURED_HOST, toConfiguredHost } from '../host-utils.js';
|
|
11
|
-
import { replayRun, modifyRun } from '../runs/replay-helpers.js';
|
|
12
|
-
import { pickerPushRun } from '../runs/push-launcher.js';
|
|
13
|
-
import { resolvePromptFlags } from './print-prompt.js';
|
|
14
|
-
import { shouldShowRunPicker } from '../runs/run-picker-mount.js';
|
|
15
|
-
import { dispatchPickerSelection } from './picker-dispatch.js';
|
|
16
|
-
import { getInteractiveTerminalSupport, requireInteractiveTerminal } from '../lib/terminal-capabilities.js';
|
|
17
|
-
export function registerImportCommand(program) {
|
|
18
|
-
const cmd = program
|
|
19
|
-
.command('import')
|
|
20
|
-
.description('Run the full pipeline: analyze → select → generate → push')
|
|
21
|
-
.option('--space-id <id>', 'Contentful space ID (required unless --skip-apply)')
|
|
22
|
-
.option('--environment-id <id>', 'Contentful environment ID (required unless --skip-apply)')
|
|
23
|
-
.option('--cma-token <token>', 'CMA personal access token (or set CONTENTFUL_MANAGEMENT_TOKEN)')
|
|
24
|
-
.option('--project <path>', 'Path to the project root to analyze', '.')
|
|
25
|
-
.option('--out <path>', 'Output directory for pipeline artifacts');
|
|
26
|
-
addAgentModelOptions(cmd, {
|
|
27
|
-
agentDescription: 'Agent to use for generate components (overrides credentials.json; falls back to "claude")',
|
|
28
|
-
modelDescription: 'Model to use for generate components (defaults to a lightweight per-agent model; override with EDS_AGENT_MODEL_<AGENT>)',
|
|
29
|
-
})
|
|
30
|
-
.option('--tokens <path>', 'Path to a DTCG tokens.json file to push alongside generated components')
|
|
31
|
-
.option('--raw-tokens <path>', 'Path to a raw token source file (SCSS, CSS variables, JS/TS, Style Dictionary, etc.) to classify and import alongside components. Bypasses the interactive token prompt.')
|
|
32
|
-
.option('--select-all', 'Select all extracted components for generation (default)')
|
|
33
|
-
.option('--select <pattern>', 'Select components matching pattern (repeatable)', (v, a) => [...a, v], [])
|
|
34
|
-
.option('--deselect <pattern>', 'Deselect components matching pattern (repeatable)', (v, a) => [...a, v], [])
|
|
35
|
-
.option('--skip-analyze', 'Skip the analyze step (uses most recent extract session)')
|
|
36
|
-
.option('--skip-generate', 'Skip the generate step (uses most recent generate session)')
|
|
37
|
-
.option('--print', 'Write components.json to --out after generation')
|
|
38
|
-
.option('--skip-apply', '(deprecated alias for --no-push) Skip pushing to Contentful')
|
|
39
|
-
.option('--no-cache', 'Re-run all steps even if output already exists')
|
|
40
|
-
.option('--yes', 'Skip interactive confirmation in apply push')
|
|
41
|
-
.option('--verbose', 'Show full agent output and all entity progress')
|
|
42
|
-
.option('--exclude-invalid', 'Automatically reject components with validation errors (empty names, collisions)')
|
|
43
|
-
.option('--viewports <path>', 'JSON file with viewport array (passed to apply push)')
|
|
44
|
-
.option('--host <url>', 'Override API base URL (passed to apply push)')
|
|
45
|
-
.option('--dry-run', "(deprecated, will change semantics in a future release) Print generate components prompt without invoking the agent. Use --print-prompt for the same behaviour explicitly, or '--dry-run --no-push' for the upcoming manifest-preview semantics.")
|
|
46
|
-
.option('--print-prompt', 'Print the generate components prompt without invoking the agent. Replaces the legacy --dry-run prompt-print behaviour on this command.')
|
|
47
|
-
.option('--auto-accept-scope', 'Accept all extracted components without prompting (for scripted/non-TTY callers)');
|
|
48
|
-
addCompositionOptions(cmd);
|
|
49
|
-
addAllowDeletionsOption(cmd);
|
|
50
|
-
cmd
|
|
51
|
-
.option('--composition-map <path>', 'Consume a hand-authored parent→children interchange map (implies --composite)')
|
|
52
|
-
.option('--composition-agent', 'Opt into agentic mapping resolution when deterministic sources find no groups (implies --composite)')
|
|
53
|
-
.option('--composition-refresh', 'Bypass the composition cache and re-resolve from scratch, forcing the agent to run (implies --composite)')
|
|
54
|
-
.option('--composition-agent-mode <mode>', "Agent mode: 'parser' (agent writes a sandboxed parser, default) or 'edges' (agent lists edges)")
|
|
55
|
-
.option('--generate-map <path>', 'Also write a composition-map skeleton from resolved edges during extract (implies --composite)')
|
|
56
|
-
.option('--prompt <stage=value>', 'Override a stage prompt (repeatable). value is a file path or literal text, e.g. --prompt composition=./p.md', (v, acc) => [...acc, v], [])
|
|
57
|
-
.option('--auto-reject-cycles', 'Automatically reject components involved in slot cycles and retry')
|
|
58
|
-
.option('--auto-filter', 'Force the AI auto-filter ON (overrides the credentials.json autoFilter preference)')
|
|
59
|
-
.option('--no-auto-filter', 'Skip the automatic AI pre-filter; jump straight to manual scope-gate (overrides the credentials.json autoFilter preference; no-op when paired with --auto-accept-scope)')
|
|
60
|
-
.option('--no-live-preview', 'Skip the automatic preview re-run after each FieldEditor save (no-op when paired with --auto-accept-scope)')
|
|
61
|
-
.option('--no-push', 'Import without pushing to Contentful. Interactive: runs the full wizard (extract → scope-gate → generate → final-review) and stops before push. Non-interactive (piped/CI): runs headless through generate. No credentials needed either way.')
|
|
62
|
-
.option('--no-save', 'Push without writing components.json / tokens.json to disk (default: save AND push)')
|
|
63
|
-
.option('--out-dir <path>', 'Save components.json / tokens.json to this directory; bypasses the inline save-path prompt')
|
|
64
|
-
.option('--on-conflict <mode>', "How to handle existing components.json / tokens.json at the save path: 'overwrite' replaces files, 'skip' writes to a timestamped subdirectory, 'fail' exits non-zero. Skips the wizard's interactive conflict gate when set.", (value) => {
|
|
65
|
-
if (!isConflictMode(value)) {
|
|
66
|
-
process.stderr.write(`Error: invalid --on-conflict value '${value}'. Use one of: overwrite, skip, fail.\n`);
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
return value;
|
|
70
|
-
})
|
|
71
|
-
.option('--select-prompt-path <path>', 'Path to a custom .md skill prompt for analyze select-agent (bypasses bundled invariants)')
|
|
72
|
-
.option('--generate-prompt-path <path>', 'Path to a custom .md skill prompt for generate components (bypasses bundled invariants)')
|
|
73
|
-
.option('--push-from-run <id-or-path>', "Push a prior run's recorded pipeline.db session to Contentful WITHOUT writing components.json / tokens.json to disk. Accepts a run-id or filesystem path that matches a recorded savePath. Credentials are resolved from flags, then the run record, then 'experiences setup', then (in a TTY) an interactive prompt.")
|
|
74
|
-
.option('--modify <id-or-path>', 'Re-open the wizard at final-review with a prior run pre-populated for field edits. Accepts a run-id or filesystem path. Pair with --overwrite or --save-as-new to pick the save mode.')
|
|
75
|
-
.option('--overwrite', "Only valid with --modify: save back to the run's recorded savePath")
|
|
76
|
-
.option('--save-as-new', 'Only valid with --modify: always save to a new path (prompts for one)')
|
|
77
|
-
.option('--force', 'Bypass staleness checks when paired with --push-from-run or --modify.')
|
|
78
|
-
.action(async (opts) => {
|
|
79
|
-
const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
|
|
80
|
-
// --modify and --push-from-run resume a recorded session; the composition
|
|
81
|
-
// mode comes from that run's record, so composition flags on the command
|
|
82
|
-
// line don't apply. Warn and clear them rather than let them mislead.
|
|
83
|
-
if (opts.modify !== undefined || opts.pushFromRun !== undefined) {
|
|
84
|
-
const passedCompositionFlags = [
|
|
85
|
-
opts.composite ? '--composite' : null,
|
|
86
|
-
opts.atomic ? '--atomic' : null,
|
|
87
|
-
opts.compositionMap ? '--composition-map' : null,
|
|
88
|
-
opts.compositionAgent ? '--composition-agent' : null,
|
|
89
|
-
opts.compositionAgentMode ? '--composition-agent-mode' : null,
|
|
90
|
-
opts.compositionRefresh ? '--composition-refresh' : null,
|
|
91
|
-
opts.generateMap ? '--generate-map' : null,
|
|
92
|
-
].filter((f) => f !== null);
|
|
93
|
-
if (passedCompositionFlags.length > 0) {
|
|
94
|
-
const entry = opts.modify !== undefined ? '--modify' : '--push-from-run';
|
|
95
|
-
process.stderr.write(`Note: ${passedCompositionFlags.join(', ')} ignored with ${entry} — composition mode comes from the recorded run.\n`);
|
|
96
|
-
opts.composite = undefined;
|
|
97
|
-
opts.atomic = undefined;
|
|
98
|
-
opts.compositionMap = undefined;
|
|
99
|
-
opts.compositionAgent = undefined;
|
|
100
|
-
opts.compositionAgentMode = undefined;
|
|
101
|
-
opts.compositionRefresh = undefined;
|
|
102
|
-
opts.generateMap = undefined;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
if (opts.pushFromRun !== undefined) {
|
|
106
|
-
if (opts.modify !== undefined) {
|
|
107
|
-
process.stderr.write('Error: --push-from-run and --modify are mutually exclusive. --push-from-run pushes the recorded session; --modify re-opens the wizard for edits.\n');
|
|
108
|
-
process.exit(1);
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
if (opts.project !== '.') {
|
|
112
|
-
process.stderr.write('Error: --push-from-run and --project are mutually exclusive. The project path is read from the recorded run.\n');
|
|
113
|
-
process.exit(1);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (opts.save === false) {
|
|
117
|
-
process.stderr.write('Error: --push-from-run and --no-save are mutually exclusive. --push-from-run never writes to disk.\n');
|
|
118
|
-
process.exit(1);
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
if (opts.push === false) {
|
|
122
|
-
process.stderr.write('Error: --push-from-run and --no-push are mutually exclusive. Pushing is the whole point of --push-from-run.\n');
|
|
123
|
-
process.exit(1);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
if (opts.overwrite || opts.saveAsNew) {
|
|
127
|
-
process.stderr.write('Error: --overwrite and --save-as-new only apply with --modify.\n');
|
|
128
|
-
process.exit(1);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
try {
|
|
132
|
-
await replayRun({
|
|
133
|
-
runIdOrPath: opts.pushFromRun,
|
|
134
|
-
...(opts.spaceId ? { spaceId: opts.spaceId } : {}),
|
|
135
|
-
...(opts.environmentId ? { environmentId: opts.environmentId } : {}),
|
|
136
|
-
...(opts.cmaToken ? { cmaToken: opts.cmaToken } : {}),
|
|
137
|
-
...(opts.host ? { host: opts.host } : {}),
|
|
138
|
-
interactive: interactiveTerminalSupported,
|
|
139
|
-
...(opts.force ? { force: true } : {}),
|
|
140
|
-
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
141
|
-
});
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
catch (err) {
|
|
145
|
-
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
|
146
|
-
process.exit(1);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (opts.modify !== undefined) {
|
|
151
|
-
if (opts.project !== '.') {
|
|
152
|
-
process.stderr.write('Error: --modify and --project are mutually exclusive. The project path is read from the recorded run.\n');
|
|
153
|
-
process.exit(1);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
if (opts.overwrite && opts.saveAsNew) {
|
|
157
|
-
process.stderr.write('Error: --overwrite and --save-as-new are mutually exclusive.\n');
|
|
158
|
-
process.exit(1);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
requireInteractiveTerminal({
|
|
162
|
-
alternative: 'start a fresh headless import with `--yes` and the required credentials',
|
|
163
|
-
});
|
|
164
|
-
try {
|
|
165
|
-
await modifyRun({
|
|
166
|
-
runIdOrPath: opts.modify,
|
|
167
|
-
...(opts.overwrite ? { overwrite: true } : {}),
|
|
168
|
-
...(opts.saveAsNew ? { saveAsNew: true } : {}),
|
|
169
|
-
...(opts.outDir ? { outDir: opts.outDir } : {}),
|
|
170
|
-
...(opts.force ? { force: true } : {}),
|
|
171
|
-
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
172
|
-
});
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
catch (err) {
|
|
176
|
-
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
|
177
|
-
process.exit(1);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (opts.overwrite || opts.saveAsNew) {
|
|
182
|
-
process.stderr.write('Error: --overwrite and --save-as-new require --modify.\n');
|
|
183
|
-
process.exit(1);
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
if (opts.save === false && opts.push === false) {
|
|
187
|
-
process.stderr.write('Error: --no-save and --no-push together would do nothing. Pick one or neither.\n');
|
|
188
|
-
process.exit(1);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
if (opts.save === false && opts.outDir) {
|
|
192
|
-
process.stderr.write('Error: --no-save and --out-dir are mutually exclusive. --no-save disables disk writes; --out-dir picks a directory for them.\n');
|
|
193
|
-
process.exit(1);
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
if (opts.save === false && opts.onConflict) {
|
|
197
|
-
process.stderr.write('Error: --no-save and --on-conflict are mutually exclusive. --no-save disables disk writes; --on-conflict only applies when files are being written.\n');
|
|
198
|
-
process.exit(1);
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
if (opts.rawTokens !== undefined) {
|
|
202
|
-
if (opts.tokens !== undefined) {
|
|
203
|
-
process.stderr.write('Error: --raw-tokens and --tokens are mutually exclusive: --raw-tokens is the source file to classify, --tokens is a pre-classified DTCG sidecar.\n');
|
|
204
|
-
process.exit(1);
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const { access } = await import('node:fs/promises');
|
|
208
|
-
try {
|
|
209
|
-
await access(opts.rawTokens);
|
|
210
|
-
}
|
|
211
|
-
catch {
|
|
212
|
-
process.stderr.write(`Error: --raw-tokens: file not found: ${opts.rawTokens}\n`);
|
|
213
|
-
process.exit(1);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const promptFlags = resolvePromptFlags({
|
|
218
|
-
...(opts.dryRun !== undefined ? { dryRun: opts.dryRun } : {}),
|
|
219
|
-
...(opts.printPrompt !== undefined ? { printPrompt: opts.printPrompt } : {}),
|
|
220
|
-
});
|
|
221
|
-
if (promptFlags.deprecationNotice) {
|
|
222
|
-
process.stderr.write(promptFlags.deprecationNotice);
|
|
223
|
-
}
|
|
224
|
-
const dryRunForward = promptFlags.forwardDryRun;
|
|
225
|
-
// "Don't push" is one user intent (--no-push); --skip-apply is a
|
|
226
|
-
// deprecated alias. Interactive runs (TTY) take the wizard and stop
|
|
227
|
-
// before push; non-interactive runs take the headless pipeline and stop
|
|
228
|
-
// after generate. Either way no credentials are required.
|
|
229
|
-
const noPushRequested = opts.push === false || opts.skipApply === true;
|
|
230
|
-
const isHeadless = opts.skipAnalyze ||
|
|
231
|
-
opts.skipGenerate ||
|
|
232
|
-
// A "don't push" request on a non-TTY is a headless intent (the wizard
|
|
233
|
-
// needs a TTY); in a TTY it stays interactive and is NOT headless.
|
|
234
|
-
(noPushRequested && !interactiveTerminalSupported) ||
|
|
235
|
-
!!opts.spaceId ||
|
|
236
|
-
!!opts.environmentId ||
|
|
237
|
-
!!opts.cmaToken ||
|
|
238
|
-
opts.yes ||
|
|
239
|
-
dryRunForward ||
|
|
240
|
-
false;
|
|
241
|
-
const autoAcceptScope = opts.autoAcceptScope ?? false;
|
|
242
|
-
if (!interactiveTerminalSupported && !isHeadless && !autoAcceptScope) {
|
|
243
|
-
requireInteractiveTerminal({
|
|
244
|
-
alternative: 'use headless flags such as `--yes` with credentials, or `--no-push --auto-accept-scope`',
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
if (interactiveTerminalSupported && !isHeadless) {
|
|
248
|
-
const { render } = await import('ink');
|
|
249
|
-
const { createElement } = await import('react');
|
|
250
|
-
const { WizardApp } = await import('./tui/WizardApp.js');
|
|
251
|
-
const creds = await readExperiencesCredentials();
|
|
252
|
-
const resolvedAgent = resolveAgent(opts.agent, creds.agent);
|
|
253
|
-
const resolvedModel = resolveModel(opts.model, creds.agentModel);
|
|
254
|
-
const resolvedCompositionMode = resolveCompositionMode(opts, creds.compositionMode);
|
|
255
|
-
const pickerDecision = await shouldShowRunPicker({
|
|
256
|
-
flags: {
|
|
257
|
-
...(opts.pushFromRun !== undefined ? { pushFromRun: opts.pushFromRun } : {}),
|
|
258
|
-
...(opts.modify !== undefined ? { modify: opts.modify } : {}),
|
|
259
|
-
...(opts.project !== '.' ? { project: opts.project } : {}),
|
|
260
|
-
...(opts.autoAcceptScope ? { autoAcceptScope: true } : {}),
|
|
261
|
-
...(opts.dryRun ? { dryRun: true } : {}),
|
|
262
|
-
},
|
|
263
|
-
isTTY: !!process.stdin.isTTY,
|
|
264
|
-
});
|
|
265
|
-
let pickerSelection = null;
|
|
266
|
-
let unmountInk = null;
|
|
267
|
-
const pickerProps = {};
|
|
268
|
-
if (pickerDecision.shouldShow) {
|
|
269
|
-
pickerProps.initialRuns = pickerDecision.runs;
|
|
270
|
-
pickerProps.onRunPicked = (selection) => {
|
|
271
|
-
pickerSelection = selection;
|
|
272
|
-
unmountInk?.();
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
const { waitUntilExit, unmount } = render(createElement(WizardApp, {
|
|
276
|
-
initialSpaceId: creds.spaceId,
|
|
277
|
-
initialEnvironmentId: creds.environmentId || 'master',
|
|
278
|
-
initialCmaToken: creds.cmaToken,
|
|
279
|
-
initialHost: toConfiguredHost(opts.host ?? creds.host) ?? DEFAULT_CONFIGURED_HOST,
|
|
280
|
-
initialAgent: resolvedAgent,
|
|
281
|
-
...(resolvedModel ? { initialModel: resolvedModel } : {}),
|
|
282
|
-
initialProjectPath: opts.project !== '.' ? resolve(opts.project) : undefined,
|
|
283
|
-
host: opts.host,
|
|
284
|
-
autoAcceptScope,
|
|
285
|
-
autoRejectCycles: opts.autoRejectCycles ?? false,
|
|
286
|
-
compositionMode: resolvedCompositionMode,
|
|
287
|
-
...(opts.compositionMap ? { compositionMap: opts.compositionMap } : {}),
|
|
288
|
-
...(opts.compositionAgent ? { compositionAgent: true } : {}),
|
|
289
|
-
...(opts.compositionAgentMode ? { compositionAgentMode: opts.compositionAgentMode } : {}),
|
|
290
|
-
...(opts.compositionRefresh ? { compositionRefresh: true } : {}),
|
|
291
|
-
...(opts.generateMap ? { generateMap: opts.generateMap } : {}),
|
|
292
|
-
...(opts.prompt && opts.prompt.length > 0 ? { promptOverrides: opts.prompt } : {}),
|
|
293
|
-
noCache: opts.cache === false,
|
|
294
|
-
autoFilter: resolveAutoFilter({ autoFilter: opts.autoFilter }, creds.autoFilter),
|
|
295
|
-
livePreview: opts.livePreview !== false,
|
|
296
|
-
noPush: noPushRequested,
|
|
297
|
-
noSave: opts.save === false,
|
|
298
|
-
...(opts.outDir ? { outDirOverride: resolve(opts.outDir) } : {}),
|
|
299
|
-
...(opts.onConflict ? { onConflictMode: opts.onConflict } : {}),
|
|
300
|
-
selectPromptPath: opts.selectPromptPath ?? creds.selectPromptPath,
|
|
301
|
-
generatePromptPath: opts.generatePromptPath ?? creds.generatePromptPath,
|
|
302
|
-
...(opts.rawTokens ? { initialRawTokensPath: resolve(opts.rawTokens) } : {}),
|
|
303
|
-
allowDeletions: opts.allowDeletions === true,
|
|
304
|
-
...pickerProps,
|
|
305
|
-
}));
|
|
306
|
-
unmountInk = unmount;
|
|
307
|
-
await waitUntilExit();
|
|
308
|
-
if (pickerSelection) {
|
|
309
|
-
await dispatchPickerSelection(pickerSelection, {
|
|
310
|
-
...(opts.spaceId ? { spaceId: opts.spaceId } : {}),
|
|
311
|
-
...(opts.environmentId ? { environmentId: opts.environmentId } : {}),
|
|
312
|
-
...(opts.cmaToken ? { cmaToken: opts.cmaToken } : {}),
|
|
313
|
-
...(opts.host ? { host: opts.host } : {}),
|
|
314
|
-
...(opts.outDir ? { outDir: opts.outDir } : {}),
|
|
315
|
-
...(opts.overwrite ? { overwrite: true } : {}),
|
|
316
|
-
...(opts.saveAsNew ? { saveAsNew: true } : {}),
|
|
317
|
-
...(opts.force ? { force: true } : {}),
|
|
318
|
-
}, { replayRun, modifyRun, pickerPushRun });
|
|
319
|
-
}
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
// --no-push (and its deprecated alias --skip-apply) both mean "stop
|
|
323
|
-
// before the push" on the headless path — so neither requires credentials.
|
|
324
|
-
const skipApply = noPushRequested;
|
|
325
|
-
const spaceId = opts.spaceId ?? process.env['CONTENTFUL_SPACE_ID'];
|
|
326
|
-
const environmentId = opts.environmentId ?? process.env['CONTENTFUL_ENVIRONMENT_ID'];
|
|
327
|
-
const cmaToken = opts.cmaToken ?? process.env['CONTENTFUL_MANAGEMENT_TOKEN'];
|
|
328
|
-
if (!skipApply && (!spaceId || !environmentId || !cmaToken)) {
|
|
329
|
-
process.stderr.write('Error: --space-id (or CONTENTFUL_SPACE_ID), --environment-id (or CONTENTFUL_ENVIRONMENT_ID), and --cma-token (or CONTENTFUL_MANAGEMENT_TOKEN) are required unless --no-push is set.\n');
|
|
330
|
-
process.exit(1);
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
const projectRoot = resolve(opts.project);
|
|
334
|
-
const outDir = opts.out ? resolve(opts.out) : join(projectRoot, '.contentful');
|
|
335
|
-
const headlessCreds = await readExperiencesCredentials();
|
|
336
|
-
const headlessAgent = resolveAgent(opts.agent, headlessCreds.agent);
|
|
337
|
-
const headlessModel = resolveModel(opts.model, headlessCreds.agentModel);
|
|
338
|
-
const headlessCompositionMode = resolveCompositionMode(opts, headlessCreds.compositionMode);
|
|
339
|
-
const result = await runPipeline({
|
|
340
|
-
project: projectRoot,
|
|
341
|
-
out: outDir,
|
|
342
|
-
spaceId,
|
|
343
|
-
environmentId,
|
|
344
|
-
cmaToken,
|
|
345
|
-
agent: headlessAgent,
|
|
346
|
-
model: headlessModel,
|
|
347
|
-
tokens: opts.tokens,
|
|
348
|
-
selectAll: opts.selectAll,
|
|
349
|
-
select: opts.select.length > 0 ? opts.select : undefined,
|
|
350
|
-
deselect: opts.deselect.length > 0 ? opts.deselect : undefined,
|
|
351
|
-
skipAnalyze: opts.skipAnalyze ?? false,
|
|
352
|
-
skipGenerate: opts.skipGenerate ?? false,
|
|
353
|
-
print: opts.print ?? false,
|
|
354
|
-
skipApply,
|
|
355
|
-
noCache: opts.cache === false,
|
|
356
|
-
yes: opts.yes ?? false,
|
|
357
|
-
verbose: opts.verbose ?? false,
|
|
358
|
-
excludeInvalid: opts.excludeInvalid ?? false,
|
|
359
|
-
viewports: opts.viewports,
|
|
360
|
-
host: opts.host,
|
|
361
|
-
dryRun: dryRunForward,
|
|
362
|
-
selectPromptPath: opts.selectPromptPath,
|
|
363
|
-
autoRejectCycles: opts.autoRejectCycles ?? false,
|
|
364
|
-
allowDeletions: opts.allowDeletions ?? false,
|
|
365
|
-
compositionMode: headlessCompositionMode,
|
|
366
|
-
...(opts.compositionMap ? { compositionMap: opts.compositionMap } : {}),
|
|
367
|
-
...(opts.compositionAgent ? { compositionAgent: true } : {}),
|
|
368
|
-
...(opts.compositionAgentMode ? { compositionAgentMode: opts.compositionAgentMode } : {}),
|
|
369
|
-
...(opts.compositionRefresh ? { compositionRefresh: true } : {}),
|
|
370
|
-
...(opts.generateMap ? { generateMap: opts.generateMap } : {}),
|
|
371
|
-
...(opts.prompt && opts.prompt.length > 0 ? { promptOverrides: opts.prompt } : {}),
|
|
372
|
-
}, (line) => process.stderr.write(line + '\n'));
|
|
373
|
-
const hasFailed = result.steps.some((s) => s.status === 'failed');
|
|
374
|
-
if (!process.stdout.isTTY) {
|
|
375
|
-
const json = JSON.stringify(result, null, 2) + '\n';
|
|
376
|
-
await new Promise((res) => process.stdout.write(json, () => res()));
|
|
377
|
-
}
|
|
378
|
-
process.exit(hasFailed ? 1 : 0);
|
|
379
|
-
});
|
|
380
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { findAllAncestors } from '../analyze/lineage.js';
|
|
2
|
-
export function computeCycleAutoRejectTargets(slotCycles, graph) {
|
|
3
|
-
const targets = new Set();
|
|
4
|
-
const participants = new Set();
|
|
5
|
-
for (const cyc of slotCycles)
|
|
6
|
-
for (const p of cyc.path)
|
|
7
|
-
participants.add(p);
|
|
8
|
-
for (const p of participants) {
|
|
9
|
-
targets.add(p);
|
|
10
|
-
for (const anc of findAllAncestors(p, graph))
|
|
11
|
-
targets.add(anc);
|
|
12
|
-
}
|
|
13
|
-
return targets;
|
|
14
|
-
}
|