@contentful/experience-design-system-cli 2.15.1-dev-build-074e179.0 → 2.15.1-dev-build-b11e821.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
CHANGED
|
@@ -306,7 +306,7 @@ export function registerAnalyzeSelectAgentCommand(program) {
|
|
|
306
306
|
.option('--session <id>', 'Session ID from analyze extract (defaults to most recent)')
|
|
307
307
|
.option('--project-root <path>', 'Project root for resolving component source files')
|
|
308
308
|
.option('--agent <name>', 'Agent to use: claude, codex, opencode, cursor (defaults to value saved by experiences setup)')
|
|
309
|
-
.option('--model <name>', 'Model to use (defaults to a
|
|
309
|
+
.option('--model <name>', 'Model to use (defaults to a cheap per-agent model; override with --model or EDS_AGENT_MODEL_<AGENT>)')
|
|
310
310
|
.option('--verbose', 'Show full agent output including reasoning text')
|
|
311
311
|
.option('--dry-run', 'Print the prompt for the first component without invoking the agent')
|
|
312
312
|
.option('--exclude-invalid', 'Auto-reject components with validation errors instead of failing loud (LLM cannot fix structural issues)')
|
|
@@ -89,6 +89,14 @@ export interface ParsedToolCalls {
|
|
|
89
89
|
export declare function parseToolCallLines(stdout: string): ParsedToolCalls;
|
|
90
90
|
export declare function parseTokenToolCallLines(stdout: string): ParsedTokenToolCalls;
|
|
91
91
|
export declare function resolveBinary(agent: AgentName): string;
|
|
92
|
+
/**
|
|
93
|
+
* Resolve the model for an agent. Explicit flag/creds value wins, then a
|
|
94
|
+
* per-agent `EDS_AGENT_MODEL_<AGENT>` env override (mirrors the
|
|
95
|
+
* `EDS_AGENT_BINARY_<AGENT>` pattern), otherwise the cheap default for that
|
|
96
|
+
* agent.
|
|
97
|
+
*/
|
|
98
|
+
export declare function resolveAgentModel(agent: AgentName, explicit?: string): string;
|
|
99
|
+
export declare function buildArgs(agent: AgentName, prompt: string, model?: string, promptViaStdin?: boolean): string[];
|
|
92
100
|
export declare function runAgent(options: {
|
|
93
101
|
agent: AgentName;
|
|
94
102
|
prompt: string;
|
|
@@ -105,4 +113,11 @@ export declare function runAgent(options: {
|
|
|
105
113
|
}): Promise<AgentRunResult>;
|
|
106
114
|
export type AgentAuthStatus = 'ok' | 'unauthenticated' | 'not-found';
|
|
107
115
|
export declare function checkAgentAuth(agent: AgentName): Promise<AgentAuthStatus>;
|
|
116
|
+
/**
|
|
117
|
+
* Build a diagnostic string from a failed agent run, surfacing the agent's own
|
|
118
|
+
* stderr (or stdout, when stderr is empty) so callers never emit a context-free
|
|
119
|
+
* "agent failed" (AIS-392 B1). `exitCode === 0` with no output is treated as the
|
|
120
|
+
* "produced no tool calls" case.
|
|
121
|
+
*/
|
|
122
|
+
export declare function describeAgentFailure(result: AgentRunResult, maxDetail?: number): string;
|
|
108
123
|
export declare function extractSentinelOutput(stdout: string): string | null | 'multiple';
|
|
@@ -211,37 +211,55 @@ const AGENT_BINARIES = {
|
|
|
211
211
|
opencode: 'opencode',
|
|
212
212
|
cursor: 'cursor-agent',
|
|
213
213
|
};
|
|
214
|
-
|
|
214
|
+
export function resolveBinary(agent) {
|
|
215
|
+
const envKey = `EDS_AGENT_BINARY_${agent.toUpperCase()}`;
|
|
216
|
+
const override = process.env[envKey];
|
|
217
|
+
if (override && override.trim())
|
|
218
|
+
return override.trim();
|
|
219
|
+
return AGENT_BINARIES[agent];
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Default models per agent — cheap/fast picks to control cost when no explicit
|
|
223
|
+
* model is configured. cursor uses `gpt-mini` (verified alias from
|
|
224
|
+
* GetUsableModels; haiku is not available in cursor's model catalog).
|
|
225
|
+
*/
|
|
215
226
|
const DEFAULT_MODELS = {
|
|
216
227
|
claude: 'haiku',
|
|
217
228
|
codex: 'gpt-5.4-mini', // requires OPENAI_API_KEY; ChatGPT account users must pass --model
|
|
218
229
|
opencode: 'claude-haiku-4-5',
|
|
219
|
-
cursor: '
|
|
230
|
+
cursor: 'gpt-mini', // cursor alias for gpt-5.4-mini-medium; haiku not in cursor's catalog
|
|
220
231
|
};
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Resolve the model for an agent. Explicit flag/creds value wins, then a
|
|
234
|
+
* per-agent `EDS_AGENT_MODEL_<AGENT>` env override (mirrors the
|
|
235
|
+
* `EDS_AGENT_BINARY_<AGENT>` pattern), otherwise the cheap default for that
|
|
236
|
+
* agent.
|
|
237
|
+
*/
|
|
238
|
+
export function resolveAgentModel(agent, explicit) {
|
|
239
|
+
if (explicit && explicit.trim())
|
|
240
|
+
return explicit.trim();
|
|
241
|
+
const override = process.env[`EDS_AGENT_MODEL_${agent.toUpperCase()}`];
|
|
224
242
|
if (override && override.trim())
|
|
225
243
|
return override.trim();
|
|
226
|
-
return
|
|
244
|
+
return DEFAULT_MODELS[agent];
|
|
227
245
|
}
|
|
228
|
-
function buildArgs(agent, prompt, model, promptViaStdin = false) {
|
|
229
|
-
const
|
|
246
|
+
export function buildArgs(agent, prompt, model, promptViaStdin = false) {
|
|
247
|
+
const modelArg = ['--model', resolveAgentModel(agent, model)];
|
|
230
248
|
// When the prompt is delivered on stdin, omit it from argv — a large prompt
|
|
231
249
|
// as a command-line argument overflows ARG_MAX (spawn E2BIG). All four CLIs
|
|
232
250
|
// read the prompt from stdin when it isn't passed positionally.
|
|
233
251
|
const promptArg = promptViaStdin ? [] : [prompt];
|
|
234
252
|
switch (agent) {
|
|
235
253
|
case 'claude':
|
|
236
|
-
return ['--print',
|
|
254
|
+
return ['--print', ...modelArg, ...promptArg];
|
|
237
255
|
case 'codex':
|
|
238
256
|
// --dangerously-bypass-approvals-and-sandbox required for non-interactive use
|
|
239
|
-
return ['exec',
|
|
257
|
+
return ['exec', ...modelArg, '--dangerously-bypass-approvals-and-sandbox', ...promptArg];
|
|
240
258
|
case 'opencode':
|
|
241
|
-
return ['run',
|
|
259
|
+
return ['run', ...modelArg, ...promptArg];
|
|
242
260
|
case 'cursor':
|
|
243
261
|
// cursor-agent uses --print for non-interactive stdout output
|
|
244
|
-
return ['--print',
|
|
262
|
+
return ['--print', ...modelArg, ...promptArg];
|
|
245
263
|
}
|
|
246
264
|
}
|
|
247
265
|
export async function runAgent(options) {
|
|
@@ -319,13 +337,12 @@ export async function runAgent(options) {
|
|
|
319
337
|
});
|
|
320
338
|
}
|
|
321
339
|
export async function checkAgentAuth(agent) {
|
|
322
|
-
if (agent !== 'claude')
|
|
323
|
-
return 'ok';
|
|
324
340
|
const binary = resolveBinary(agent);
|
|
325
|
-
// Verify the binary exists first
|
|
326
|
-
//
|
|
327
|
-
// shells doesn't
|
|
328
|
-
//
|
|
341
|
+
// Verify the selected agent's binary exists first — for EVERY agent, not
|
|
342
|
+
// just claude. When `binary` is an absolute path (e.g. set via
|
|
343
|
+
// EDS_AGENT_BINARY_<AGENT>=/opt/custom/bin), `which` on some shells doesn't
|
|
344
|
+
// resolve it — check the filesystem directly for absolute paths, and fall
|
|
345
|
+
// back to `which` for bare names on $PATH.
|
|
329
346
|
const binaryExists = await new Promise((resolve) => {
|
|
330
347
|
if (binary.startsWith('/')) {
|
|
331
348
|
import('node:fs/promises').then((fs) => fs.access(binary).then(() => resolve(true), () => resolve(false)));
|
|
@@ -336,6 +353,11 @@ export async function checkAgentAuth(agent) {
|
|
|
336
353
|
});
|
|
337
354
|
if (!binaryExists)
|
|
338
355
|
return 'not-found';
|
|
356
|
+
// Only Claude exposes `auth status --json`. Non-Claude agents are considered
|
|
357
|
+
// authenticated once their binary is present — never gate them on claude
|
|
358
|
+
// (AIS-392 B3: Codex-via-Bedrock users were blocked by a claude check).
|
|
359
|
+
if (agent !== 'claude')
|
|
360
|
+
return 'ok';
|
|
339
361
|
// Use `claude auth status` — fast, no API call, works regardless of which
|
|
340
362
|
// auth provider (direct, Bedrock, Vertex) or whether AWS_PROFILE is set.
|
|
341
363
|
return new Promise((resolve) => {
|
|
@@ -373,6 +395,17 @@ export async function checkAgentAuth(agent) {
|
|
|
373
395
|
});
|
|
374
396
|
});
|
|
375
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Build a diagnostic string from a failed agent run, surfacing the agent's own
|
|
400
|
+
* stderr (or stdout, when stderr is empty) so callers never emit a context-free
|
|
401
|
+
* "agent failed" (AIS-392 B1). `exitCode === 0` with no output is treated as the
|
|
402
|
+
* "produced no tool calls" case.
|
|
403
|
+
*/
|
|
404
|
+
export function describeAgentFailure(result, maxDetail = 800) {
|
|
405
|
+
const base = result.exitCode !== 0 ? `agent exited with code ${result.exitCode}` : 'agent produced no tool calls';
|
|
406
|
+
const detail = (result.stderr.trim() || result.stdout.trim()).slice(-maxDetail).trim();
|
|
407
|
+
return detail ? `${base} — ${detail}` : base;
|
|
408
|
+
}
|
|
376
409
|
export function extractSentinelOutput(stdout) {
|
|
377
410
|
const START = '<<<EDS_OUTPUT_START>>>';
|
|
378
411
|
const END = '<<<EDS_OUTPUT_END>>>';
|
|
@@ -4,7 +4,7 @@ import { access, readFile, readdir, stat } from 'node:fs/promises';
|
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
5
|
import { execFile } from 'node:child_process';
|
|
6
6
|
import { promisify } from 'node:util';
|
|
7
|
-
import { parseToolCallLines, parseTokenToolCallLines, resolveBinary, runAgent, } from './agent-runner.js';
|
|
7
|
+
import { describeAgentFailure, parseToolCallLines, parseTokenToolCallLines, resolveBinary, runAgent, } from './agent-runner.js';
|
|
8
8
|
import { OutputFormatter, c } from '../output/format.js';
|
|
9
9
|
import { formatGenerateProgressLine } from './progress.js';
|
|
10
10
|
import { buildPrompt, resolveSkillPath } from './prompt-builder.js';
|
|
@@ -217,12 +217,12 @@ async function runOneComponent(agent, model, db, sessionId, component, tokensInl
|
|
|
217
217
|
};
|
|
218
218
|
}
|
|
219
219
|
if (result.exitCode !== 0) {
|
|
220
|
-
lastError =
|
|
220
|
+
lastError = describeAgentFailure(result);
|
|
221
221
|
continue;
|
|
222
222
|
}
|
|
223
223
|
const { calls, warnings } = parseToolCallLines(result.stdout);
|
|
224
224
|
if (calls.length === 0) {
|
|
225
|
-
lastError =
|
|
225
|
+
lastError = describeAgentFailure(result);
|
|
226
226
|
continue;
|
|
227
227
|
}
|
|
228
228
|
const applied = applyToolCalls(db, sessionId, component.component_id, component.name, calls, warnings);
|
|
@@ -452,7 +452,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
452
452
|
// Machine-parseable summary on stdout for the wizard / orchestrator.
|
|
453
453
|
process.stdout.write(`renamed-slots: ${totalRenamedSlots}\n`);
|
|
454
454
|
if (generated.length === 0 && cachedResults.length === 0) {
|
|
455
|
-
die(
|
|
455
|
+
die(`Error: all ${componentResults.length} component(s) failed to generate — see the per-component errors above.`);
|
|
456
456
|
}
|
|
457
457
|
}
|
|
458
458
|
else if (skill === 'tokens') {
|
|
@@ -570,7 +570,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
570
570
|
function addAgentFlags(cmd) {
|
|
571
571
|
return cmd
|
|
572
572
|
.option('--agent <name>', 'Agent to use: claude, codex, opencode, cursor (defaults to value saved by experiences setup)')
|
|
573
|
-
.option('--model <name>', 'Model to use (defaults to a
|
|
573
|
+
.option('--model <name>', 'Model to use (defaults to a cheap per-agent model; override with --model or EDS_AGENT_MODEL_<AGENT>)')
|
|
574
574
|
.option('--verbose', 'Show full agent output including reasoning text')
|
|
575
575
|
.option('--dry-run', 'Print the prompt without invoking the agent')
|
|
576
576
|
.option('--no-cache', 'Bypass ALL fine-grained caches (extract, select, generate) and force AI re-run. ' +
|
|
@@ -20,7 +20,7 @@ export function registerImportCommand(program) {
|
|
|
20
20
|
.option('--project <path>', 'Path to the project root to analyze', '.')
|
|
21
21
|
.option('--out <path>', 'Output directory for pipeline artifacts')
|
|
22
22
|
.option('--agent <name>', 'Agent to use for generate components (overrides credentials.json; falls back to "claude")')
|
|
23
|
-
.option('--model <name>', 'Model to use for generate components (defaults to a
|
|
23
|
+
.option('--model <name>', 'Model to use for generate components (defaults to a cheap per-agent model; override with --model or EDS_AGENT_MODEL_<AGENT>)')
|
|
24
24
|
.option('--tokens <path>', 'Path to a DTCG tokens.json file to push alongside generated components')
|
|
25
25
|
.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.')
|
|
26
26
|
.option('--select-all', 'Select all extracted components for generation (default)')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/experience-design-system-cli",
|
|
3
|
-
"version": "2.15.1-dev-build-
|
|
3
|
+
"version": "2.15.1-dev-build-b11e821.0",
|
|
4
4
|
"description": "Contentful Experiences design system import CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"react": "^18.3.1",
|
|
35
35
|
"react-devtools-core": "^4.19.1",
|
|
36
36
|
"react-dom": "^18.3.1",
|
|
37
|
-
"@contentful/experience-design-system-extraction": "2.15.1-dev-build-
|
|
38
|
-
"@contentful/experience-design-system-types": "2.15.1-dev-build-
|
|
37
|
+
"@contentful/experience-design-system-extraction": "2.15.1-dev-build-b11e821.0",
|
|
38
|
+
"@contentful/experience-design-system-types": "2.15.1-dev-build-b11e821.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@tsconfig/node24": "^24.0.3",
|