@contentful/experience-design-system-cli 2.34.5-dev-build-3e657f24.0 → 2.34.5-dev-build-b70b5f29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- package/dist/src/index.js +692 -497
- package/dist/src/lib/agent-output.d.ts +4 -0
- package/package.json +6 -6
package/dist/src/index.js
CHANGED
|
@@ -160,21 +160,253 @@ var init_render_with_goodbye = __esm({
|
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
// packages/experience-design-system-generation/dist/src/agent
|
|
163
|
+
// packages/experience-design-system-generation/dist/src/generate/model/agent.js
|
|
164
164
|
function isAgentName(value) {
|
|
165
165
|
return AGENT_NAMES.includes(value);
|
|
166
166
|
}
|
|
167
167
|
var AGENT_NAMES, DEFAULT_AGENT_NAME;
|
|
168
|
-
var
|
|
169
|
-
"packages/experience-design-system-generation/dist/src/agent
|
|
168
|
+
var init_agent = __esm({
|
|
169
|
+
"packages/experience-design-system-generation/dist/src/generate/model/agent.js"() {
|
|
170
170
|
"use strict";
|
|
171
171
|
AGENT_NAMES = ["claude", "codex", "opencode", "cursor", "copilot"];
|
|
172
172
|
DEFAULT_AGENT_NAME = "claude";
|
|
173
173
|
}
|
|
174
174
|
});
|
|
175
175
|
|
|
176
|
-
// packages/experience-design-system-generation/dist/src/agent-
|
|
176
|
+
// packages/experience-design-system-generation/dist/src/generate/services/agent-configuration-service.js
|
|
177
|
+
function resolveBinary(agent) {
|
|
178
|
+
const envKey = `EDS_AGENT_BINARY_${agent.toUpperCase()}`;
|
|
179
|
+
const override = process.env[envKey];
|
|
180
|
+
if (override && override.trim())
|
|
181
|
+
return override.trim();
|
|
182
|
+
return AGENT_BINARIES[agent];
|
|
183
|
+
}
|
|
184
|
+
function resolveAgentEnvironment(agent, bedrock) {
|
|
185
|
+
return bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
|
|
186
|
+
}
|
|
187
|
+
function agentSupportsBedrock(agent) {
|
|
188
|
+
return BEDROCK_CAPABLE_AGENTS.has(agent);
|
|
189
|
+
}
|
|
190
|
+
function resolveAgentModel(agent, explicit, bedrock = false) {
|
|
191
|
+
if (explicit && explicit.trim())
|
|
192
|
+
return explicit.trim();
|
|
193
|
+
const override = process.env[`EDS_AGENT_MODEL_${agent.toUpperCase()}`];
|
|
194
|
+
if (override && override.trim())
|
|
195
|
+
return override.trim();
|
|
196
|
+
if (bedrock && agent === "codex")
|
|
197
|
+
return DEFAULT_CODEX_BEDROCK_MODEL;
|
|
198
|
+
if (bedrock && agent === "opencode")
|
|
199
|
+
return withBedrockProviderPrefix(DEFAULT_OPENCODE_MODEL);
|
|
200
|
+
return DEFAULT_MODELS[agent];
|
|
201
|
+
}
|
|
202
|
+
function withBedrockProviderPrefix(model) {
|
|
203
|
+
return model.includes("/") ? model : `amazon-bedrock/${model}`;
|
|
204
|
+
}
|
|
205
|
+
function codexBedrockConfigArgs() {
|
|
206
|
+
const region = process.env.AWS_REGION?.trim() || process.env.AWS_DEFAULT_REGION?.trim() || DEFAULT_CODEX_BEDROCK_REGION;
|
|
207
|
+
return ["-c", "model_provider=amazon-bedrock", "-c", `model_providers.amazon-bedrock.region=${region}`];
|
|
208
|
+
}
|
|
209
|
+
function buildArgs(agent, prompt, model, promptViaStdin = false, bedrock = false) {
|
|
210
|
+
const resolvedModel = resolveAgentModel(agent, model, bedrock);
|
|
211
|
+
const modelArg = resolvedModel ? ["--model", resolvedModel] : [];
|
|
212
|
+
const promptArg = promptViaStdin ? [] : [prompt];
|
|
213
|
+
switch (agent) {
|
|
214
|
+
case "claude":
|
|
215
|
+
return ["--print", ...modelArg, ...promptArg];
|
|
216
|
+
case "codex": {
|
|
217
|
+
const bedrockArgs = bedrock ? codexBedrockConfigArgs() : [];
|
|
218
|
+
return ["exec", ...bedrockArgs, ...modelArg, "--dangerously-bypass-approvals-and-sandbox", ...promptArg];
|
|
219
|
+
}
|
|
220
|
+
case "opencode":
|
|
221
|
+
return ["run", ...modelArg, ...promptArg];
|
|
222
|
+
case "cursor":
|
|
223
|
+
return ["--print", ...modelArg, ...promptArg];
|
|
224
|
+
case "copilot": {
|
|
225
|
+
const copilotModel = resolveAgentModel("copilot", model);
|
|
226
|
+
const copilotModelArg = !copilotModel || copilotModel === "Auto" ? [] : ["--model", copilotModel];
|
|
227
|
+
return ["-p", ...promptArg, ...copilotModelArg, "--allow-all-tools"];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
var AGENT_BINARIES, BEDROCK_ENV_BY_AGENT, BEDROCK_CAPABLE_AGENTS, DEFAULT_CODEX_BEDROCK_REGION, DEFAULT_OPENCODE_MODEL, DEFAULT_MODELS, DEFAULT_CODEX_BEDROCK_MODEL;
|
|
232
|
+
var init_agent_configuration_service = __esm({
|
|
233
|
+
"packages/experience-design-system-generation/dist/src/generate/services/agent-configuration-service.js"() {
|
|
234
|
+
"use strict";
|
|
235
|
+
AGENT_BINARIES = {
|
|
236
|
+
claude: "claude",
|
|
237
|
+
codex: "codex",
|
|
238
|
+
opencode: "opencode",
|
|
239
|
+
cursor: "cursor-agent",
|
|
240
|
+
copilot: "copilot"
|
|
241
|
+
};
|
|
242
|
+
BEDROCK_ENV_BY_AGENT = {
|
|
243
|
+
claude: { CLAUDE_CODE_USE_BEDROCK: "1" }
|
|
244
|
+
};
|
|
245
|
+
BEDROCK_CAPABLE_AGENTS = /* @__PURE__ */ new Set(["claude", "codex", "opencode"]);
|
|
246
|
+
DEFAULT_CODEX_BEDROCK_REGION = "us-east-1";
|
|
247
|
+
DEFAULT_OPENCODE_MODEL = "claude-haiku-4-5";
|
|
248
|
+
DEFAULT_MODELS = {
|
|
249
|
+
claude: "haiku",
|
|
250
|
+
opencode: DEFAULT_OPENCODE_MODEL,
|
|
251
|
+
cursor: "gpt-mini",
|
|
252
|
+
copilot: "Auto"
|
|
253
|
+
};
|
|
254
|
+
DEFAULT_CODEX_BEDROCK_MODEL = "openai.gpt-5.6-luna";
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// packages/experience-design-system-generation/dist/src/generate/services/agent-auth-service.js
|
|
177
259
|
import { spawn } from "node:child_process";
|
|
260
|
+
async function checkAgentAuth(agent) {
|
|
261
|
+
const binary = resolveBinary(agent);
|
|
262
|
+
const binaryExists2 = await new Promise((resolve21) => {
|
|
263
|
+
if (binary.startsWith("/")) {
|
|
264
|
+
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() => resolve21(true), () => resolve21(false)));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const child = spawn(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
|
|
268
|
+
child.on("close", (code) => resolve21(code === 0));
|
|
269
|
+
});
|
|
270
|
+
if (!binaryExists2)
|
|
271
|
+
return "not-found";
|
|
272
|
+
if (agent !== "claude")
|
|
273
|
+
return "ok";
|
|
274
|
+
return new Promise((resolve21) => {
|
|
275
|
+
const child = spawn(binary, ["auth", "status", "--json"], {
|
|
276
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
277
|
+
});
|
|
278
|
+
let stdout = "";
|
|
279
|
+
let done = false;
|
|
280
|
+
const timer = setTimeout(() => {
|
|
281
|
+
if (!done) {
|
|
282
|
+
done = true;
|
|
283
|
+
child.kill("SIGTERM");
|
|
284
|
+
resolve21("unauthenticated");
|
|
285
|
+
}
|
|
286
|
+
}, 5e3);
|
|
287
|
+
child.stdout?.on("data", (chunk) => {
|
|
288
|
+
stdout += chunk.toString();
|
|
289
|
+
});
|
|
290
|
+
child.on("close", (code) => {
|
|
291
|
+
if (done)
|
|
292
|
+
return;
|
|
293
|
+
done = true;
|
|
294
|
+
clearTimeout(timer);
|
|
295
|
+
if (code !== 0) {
|
|
296
|
+
resolve21("unauthenticated");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
try {
|
|
300
|
+
const status = JSON.parse(stdout);
|
|
301
|
+
resolve21(status.loggedIn ? "ok" : "unauthenticated");
|
|
302
|
+
} catch {
|
|
303
|
+
resolve21("unauthenticated");
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
var init_agent_auth_service = __esm({
|
|
309
|
+
"packages/experience-design-system-generation/dist/src/generate/services/agent-auth-service.js"() {
|
|
310
|
+
"use strict";
|
|
311
|
+
init_agent_configuration_service();
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// packages/experience-design-system-generation/dist/src/generate/services/failure-diagnostics-service.js
|
|
316
|
+
function describeAgentFailure(result, maxDetail = 800) {
|
|
317
|
+
const base = result.exitCode !== 0 ? `agent exited with code ${result.exitCode}` : "agent produced no tool calls";
|
|
318
|
+
const detail = (result.stderr.trim() || result.stdout.trim()).slice(-maxDetail).trim();
|
|
319
|
+
return detail ? `${base} \u2014 ${detail}` : base;
|
|
320
|
+
}
|
|
321
|
+
var init_failure_diagnostics_service = __esm({
|
|
322
|
+
"packages/experience-design-system-generation/dist/src/generate/services/failure-diagnostics-service.js"() {
|
|
323
|
+
"use strict";
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// packages/experience-design-system-generation/dist/src/generate/adapters/local/local-agent-process.js
|
|
328
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
329
|
+
async function runAgent(options) {
|
|
330
|
+
const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
|
|
331
|
+
const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
|
|
332
|
+
const binary = resolveBinary(agent);
|
|
333
|
+
const useStdin2 = !!promptViaStdin;
|
|
334
|
+
const args = buildArgs(agent, prompt, model, useStdin2, bedrock);
|
|
335
|
+
const startedAt = Date.now();
|
|
336
|
+
onDebugEvent?.("run.start", {
|
|
337
|
+
agent,
|
|
338
|
+
binary,
|
|
339
|
+
model,
|
|
340
|
+
bedrock: !!bedrock,
|
|
341
|
+
timeoutMs,
|
|
342
|
+
promptLen: prompt.length,
|
|
343
|
+
promptHead: prompt.slice(0, 500)
|
|
344
|
+
});
|
|
345
|
+
return new Promise((resolve21) => {
|
|
346
|
+
const bedrockEnv = resolveAgentEnvironment(agent, bedrock);
|
|
347
|
+
const child = spawn2(binary, args, {
|
|
348
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
349
|
+
...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
|
|
350
|
+
});
|
|
351
|
+
if (useStdin2 && child.stdin) {
|
|
352
|
+
child.stdin.on("error", () => {
|
|
353
|
+
});
|
|
354
|
+
child.stdin.write(prompt, () => {
|
|
355
|
+
child.stdin?.end();
|
|
356
|
+
});
|
|
357
|
+
} else {
|
|
358
|
+
child.stdin?.end();
|
|
359
|
+
}
|
|
360
|
+
let stdout = "";
|
|
361
|
+
let stderr = "";
|
|
362
|
+
let timedOut = false;
|
|
363
|
+
let spawnError;
|
|
364
|
+
const timer = setTimeout(() => {
|
|
365
|
+
timedOut = true;
|
|
366
|
+
child.kill("SIGTERM");
|
|
367
|
+
}, timeoutMs);
|
|
368
|
+
child.stdout?.on("data", (chunk) => {
|
|
369
|
+
const text = chunk.toString();
|
|
370
|
+
stdout += text;
|
|
371
|
+
onOutput?.(text);
|
|
372
|
+
});
|
|
373
|
+
child.stderr?.on("data", (chunk) => {
|
|
374
|
+
stderr += chunk.toString();
|
|
375
|
+
});
|
|
376
|
+
child.on("error", (error) => {
|
|
377
|
+
spawnError = error;
|
|
378
|
+
});
|
|
379
|
+
child.on("close", (code, signal) => {
|
|
380
|
+
clearTimeout(timer);
|
|
381
|
+
const result = {
|
|
382
|
+
exitCode: spawnError || signal ? 1 : code ?? 1,
|
|
383
|
+
stdout,
|
|
384
|
+
stderr: spawnError ? `${stderr}${spawnError.message}` : stderr,
|
|
385
|
+
timedOut
|
|
386
|
+
};
|
|
387
|
+
onDebugEvent?.("run.end", {
|
|
388
|
+
agent,
|
|
389
|
+
model,
|
|
390
|
+
durationMs: Date.now() - startedAt,
|
|
391
|
+
exitCode: result.exitCode,
|
|
392
|
+
signal,
|
|
393
|
+
timedOut,
|
|
394
|
+
stdoutLen: stdout.length,
|
|
395
|
+
stderrLen: stderr.length,
|
|
396
|
+
stderrTail: stderr.slice(-1e3)
|
|
397
|
+
});
|
|
398
|
+
resolve21(result);
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
var init_local_agent_process = __esm({
|
|
403
|
+
"packages/experience-design-system-generation/dist/src/generate/adapters/local/local-agent-process.js"() {
|
|
404
|
+
"use strict";
|
|
405
|
+
init_agent_configuration_service();
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// packages/experience-design-system-generation/dist/src/generate/services/protocol-parser-service.js
|
|
178
410
|
function findJsonObjectEnd(line) {
|
|
179
411
|
let depth = 0;
|
|
180
412
|
let inString = false;
|
|
@@ -410,312 +642,229 @@ function parseMapTokenPropToolCallLines(stdout) {
|
|
|
410
642
|
warnings.push(`map_token_prop '${rec.component}.${String(rec.prop)}': missing or empty token_allowed \u2014 skipped`);
|
|
411
643
|
continue;
|
|
412
644
|
}
|
|
413
|
-
|
|
645
|
+
calls.push({
|
|
414
646
|
tool: "map_token_prop",
|
|
415
647
|
component: rec.component,
|
|
416
648
|
prop: rec.prop,
|
|
417
649
|
token_allowed: rec.token_allowed
|
|
418
|
-
};
|
|
419
|
-
calls.push(call);
|
|
650
|
+
});
|
|
420
651
|
}
|
|
421
652
|
return { calls, warnings };
|
|
422
653
|
}
|
|
423
|
-
function
|
|
424
|
-
const
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
654
|
+
function extractSentinelOutput(stdout) {
|
|
655
|
+
const startMarker = "<<<EDS_OUTPUT_START>>>";
|
|
656
|
+
const endMarker = "<<<EDS_OUTPUT_END>>>";
|
|
657
|
+
const startIndex = stdout.indexOf(startMarker);
|
|
658
|
+
const endIndex = stdout.indexOf(endMarker);
|
|
659
|
+
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex)
|
|
660
|
+
return null;
|
|
661
|
+
const secondStart = stdout.indexOf(startMarker, startIndex + startMarker.length);
|
|
662
|
+
if (secondStart !== -1 && secondStart < endIndex)
|
|
663
|
+
return "multiple";
|
|
664
|
+
const firstEnd = stdout.indexOf(endMarker, startIndex);
|
|
665
|
+
const secondEnd = stdout.indexOf(endMarker, firstEnd + endMarker.length);
|
|
666
|
+
if (secondEnd !== -1)
|
|
667
|
+
return "multiple";
|
|
668
|
+
return stdout.slice(startIndex + startMarker.length, endIndex).trim();
|
|
432
669
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
670
|
+
var VALID_SELECT_TOOL_NAMES, VALID_TOOL_NAMES, VALID_TOKEN_TOOL_NAMES, VALID_CDF_TYPES, VALID_CATEGORIES;
|
|
671
|
+
var init_protocol_parser_service = __esm({
|
|
672
|
+
"packages/experience-design-system-generation/dist/src/generate/services/protocol-parser-service.js"() {
|
|
673
|
+
"use strict";
|
|
674
|
+
VALID_SELECT_TOOL_NAMES = /* @__PURE__ */ new Set(["select_component", "reject_component"]);
|
|
675
|
+
VALID_TOOL_NAMES = /* @__PURE__ */ new Set(["classify_prop", "exclude_prop", "classify_component", "classify_slot"]);
|
|
676
|
+
VALID_TOKEN_TOOL_NAMES = /* @__PURE__ */ new Set(["set_token", "set_group"]);
|
|
677
|
+
VALID_CDF_TYPES = /* @__PURE__ */ new Set(["string", "richtext", "media", "enum", "token", "boolean"]);
|
|
678
|
+
VALID_CATEGORIES = /* @__PURE__ */ new Set(["content", "design", "state"]);
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
// packages/experience-design-system-generation/dist/src/generate/adapters/local/local-agent-invoker.js
|
|
683
|
+
function createLocalCliAgentInvoker(options = {}) {
|
|
684
|
+
const { onDebugEvent } = options;
|
|
685
|
+
return {
|
|
686
|
+
invoke(invokeOptions) {
|
|
687
|
+
return runAgent({ ...invokeOptions, onDebugEvent });
|
|
688
|
+
},
|
|
689
|
+
checkAuth(agent) {
|
|
690
|
+
return checkAgentAuth(agent);
|
|
691
|
+
}
|
|
692
|
+
};
|
|
444
693
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return ["-c", "model_provider=amazon-bedrock", "-c", `model_providers.amazon-bedrock.region=${region}`];
|
|
451
|
-
}
|
|
452
|
-
function buildArgs(agent, prompt, model, promptViaStdin = false, bedrock = false) {
|
|
453
|
-
const resolvedModel = resolveAgentModel(agent, model, bedrock);
|
|
454
|
-
const modelArg = resolvedModel ? ["--model", resolvedModel] : [];
|
|
455
|
-
const promptArg = promptViaStdin ? [] : [prompt];
|
|
456
|
-
switch (agent) {
|
|
457
|
-
case "claude":
|
|
458
|
-
return ["--print", ...modelArg, ...promptArg];
|
|
459
|
-
case "codex": {
|
|
460
|
-
const bedrockArgs = bedrock ? codexBedrockConfigArgs() : [];
|
|
461
|
-
return ["exec", ...bedrockArgs, ...modelArg, "--dangerously-bypass-approvals-and-sandbox", ...promptArg];
|
|
462
|
-
}
|
|
463
|
-
case "opencode":
|
|
464
|
-
return ["run", ...modelArg, ...promptArg];
|
|
465
|
-
case "cursor":
|
|
466
|
-
return ["--print", ...modelArg, ...promptArg];
|
|
467
|
-
case "copilot": {
|
|
468
|
-
const copilotModel = resolveAgentModel("copilot", model);
|
|
469
|
-
const copilotModelArg = !copilotModel || copilotModel === "Auto" ? [] : ["--model", copilotModel];
|
|
470
|
-
return ["-p", ...promptArg, ...copilotModelArg, "--allow-all-tools"];
|
|
471
|
-
}
|
|
694
|
+
var init_local_agent_invoker = __esm({
|
|
695
|
+
"packages/experience-design-system-generation/dist/src/generate/adapters/local/local-agent-invoker.js"() {
|
|
696
|
+
"use strict";
|
|
697
|
+
init_agent_auth_service();
|
|
698
|
+
init_local_agent_process();
|
|
472
699
|
}
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
// packages/experience-design-system-generation/dist/src/generate/services/preambles/components.js
|
|
703
|
+
function buildComponentsAutonomousPreamble(inputBlock) {
|
|
704
|
+
return `You are running as part of the experience-design-system-cli generate pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
|
|
705
|
+
|
|
706
|
+
Context: You are classifying a React component for **Contentful Experience Orchestration**. The result is a Component Type \u2014 a schema that tells Contentful what a marketer can configure. Properties fall into three categories:
|
|
707
|
+
- **design**: controls how the component looks (variant, size, color, layout toggles)
|
|
708
|
+
- **content**: the data a content editor fills in (text, images, URLs, rich text)
|
|
709
|
+
- **state**: runtime behavioral flags (disabled, loading, expanded, identifiers)
|
|
710
|
+
|
|
711
|
+
Your task: classify every prop and slot in the component below. Apply all judgment calls yourself \u2014 do not pause to ask for confirmation. Include a "description" field on each tool call to document your reasoning so the developer can review it afterward.
|
|
712
|
+
|
|
713
|
+
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
714
|
+
|
|
715
|
+
## Output protocol
|
|
716
|
+
|
|
717
|
+
Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object per line to stdout for each classification decision. The CLI reads your stdout line by line and writes each decision directly to the pipeline database.
|
|
718
|
+
|
|
719
|
+
The four tool calls you may emit are:
|
|
720
|
+
|
|
721
|
+
\`\`\`
|
|
722
|
+
{"tool":"classify_component","description":"<optional component-level description>","rationale":{"description":"<why this component is classified the way it is>","props":"<why these props were chosen>","slots":"<why these slots were chosen>"}}
|
|
723
|
+
|
|
724
|
+
{"tool":"classify_prop","prop":"<propName>","cdf_type":"<type>","cdf_category":"<category>","required":<bool>,"description":"<short customer-facing description>","reason":"<full internal rationale; not customer-facing>","values":["a","b"],"token_kind":"color","default":"<value>"}
|
|
725
|
+
|
|
726
|
+
{"tool":"exclude_prop","prop":"<propName>","reason":"<why excluded>"}
|
|
727
|
+
|
|
728
|
+
{"tool":"classify_slot","slot":"<slotName>","required":<bool>,"allowed_components":["ComponentName"],"description":"<reason>","rationale":"<why this slot was kept in the catalog>"}
|
|
729
|
+
\`\`\`
|
|
730
|
+
|
|
731
|
+
Rules:
|
|
732
|
+
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences around the lines.
|
|
733
|
+
- Every prop in the input must have exactly one call: either classify_prop or exclude_prop.
|
|
734
|
+
- Every slot in the input must have exactly one classify_slot call.
|
|
735
|
+
- Valid cdf_type values: string, richtext, media, enum, token, boolean
|
|
736
|
+
- Valid cdf_category values: content, design, state
|
|
737
|
+
- For enum type, always include \`values\` (non-empty string array of the variant names the prop accepts).
|
|
738
|
+
- For token type, always include \`token_kind\` (DTCG $type, e.g. "color"). **Never emit \`values\` for \`cdf_type: "token"\` props** \u2014 an enum prop's list holds variant names; a token prop's list holds design token paths, produced separately and never by you. Emitting \`values\` on a token prop makes the definition invalid.
|
|
739
|
+
- Never emit both "values" and "token_kind" on one prop.
|
|
740
|
+
- \`enum\` vs \`token\` is decided by three questions answered in order from the source shown \u2014 never from the TypeScript type. Q1: does the component look the value up, switch on it, or have a vocabulary for it (\`tokens[x]\`, \`switch (variant)\`, \`allowedValues\`)? yes \u2192 \`enum\`, stop.
|
|
741
|
+
- Q2: is the value written straight into a style or attribute (\`rx={radius}\`, \`padding: \${padding}\`)? no \u2192 not \`token\`, apply the type rules.
|
|
742
|
+
- Q3: is there a design-token reference at that use \u2014 a \`tokens.*\` parameter default, a \`tokenReference\`, an inline \`tokens.*\` / \`var(--*)\`? yes \u2192 \`token\` (cite both lines in "reason"); no \u2192 \`string\`. "Ambiguity resolves to \`enum\`" applies only when Q1\u2013Q3 cannot be answered from the source shown.
|
|
743
|
+
- CSS design props (className, style, styles, positional/geometric props: top, bottom, left, right, rotation, offset, etc.) \u2192 classify_prop, cdf_type: "string", cdf_category: "design".
|
|
744
|
+
- On classify_component, "rationale" fields are operator-facing (read-only) but may surface in customer-facing exports. The "rationale.description" field is subject to the description content rules in the skill prompt (no internal initiative names). "rationale.props" and "rationale.slots" describe your reasoning about scope; "classify_slot.rationale" explains why each slot was kept.
|
|
745
|
+
- On classify_prop, "reason" is REQUIRED and is the LLM's internal rationale \u2014 shown to the developer reviewing the import, never to end-users. "description" is the customer-facing copy and is subject to the description content rules in the skill prompt. Keep them distinct: "description" is short and customer-facing; "reason" explains your reasoning in detail.
|
|
746
|
+
- You may emit prose lines (not starting with {) anywhere \u2014 they are ignored by the parser and serve as your reasoning log.`;
|
|
473
747
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
|
|
477
|
-
const binary = resolveBinary(agent);
|
|
478
|
-
const useStdin2 = !!promptViaStdin;
|
|
479
|
-
const args = buildArgs(agent, prompt, model, useStdin2, bedrock);
|
|
480
|
-
const startedAt = Date.now();
|
|
481
|
-
onDebugEvent?.("run.start", {
|
|
482
|
-
agent,
|
|
483
|
-
binary,
|
|
484
|
-
model,
|
|
485
|
-
bedrock: !!bedrock,
|
|
486
|
-
timeoutMs,
|
|
487
|
-
promptLen: prompt.length,
|
|
488
|
-
promptHead: prompt.slice(0, 500)
|
|
489
|
-
});
|
|
490
|
-
return new Promise((resolve21) => {
|
|
491
|
-
const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
|
|
492
|
-
const child = spawn(binary, args, {
|
|
493
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
494
|
-
...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
|
|
495
|
-
});
|
|
496
|
-
if (useStdin2 && child.stdin) {
|
|
497
|
-
child.stdin.on("error", () => {
|
|
498
|
-
});
|
|
499
|
-
child.stdin.write(prompt, () => {
|
|
500
|
-
child.stdin?.end();
|
|
501
|
-
});
|
|
502
|
-
} else {
|
|
503
|
-
child.stdin?.end();
|
|
504
|
-
}
|
|
505
|
-
let stdout = "";
|
|
506
|
-
let stderr = "";
|
|
507
|
-
let timedOut = false;
|
|
508
|
-
const timer = setTimeout(() => {
|
|
509
|
-
timedOut = true;
|
|
510
|
-
child.kill("SIGTERM");
|
|
511
|
-
}, timeoutMs);
|
|
512
|
-
child.stdout?.on("data", (chunk) => {
|
|
513
|
-
const text = chunk.toString();
|
|
514
|
-
stdout += text;
|
|
515
|
-
onOutput?.(text);
|
|
516
|
-
});
|
|
517
|
-
child.stderr?.on("data", (chunk) => {
|
|
518
|
-
stderr += chunk.toString();
|
|
519
|
-
});
|
|
520
|
-
child.on("close", (code, signal) => {
|
|
521
|
-
clearTimeout(timer);
|
|
522
|
-
const result = {
|
|
523
|
-
exitCode: signal ? 1 : code ?? 1,
|
|
524
|
-
stdout,
|
|
525
|
-
stderr,
|
|
526
|
-
timedOut
|
|
527
|
-
};
|
|
528
|
-
onDebugEvent?.("run.end", {
|
|
529
|
-
agent,
|
|
530
|
-
model,
|
|
531
|
-
durationMs: Date.now() - startedAt,
|
|
532
|
-
exitCode: result.exitCode,
|
|
533
|
-
signal,
|
|
534
|
-
timedOut,
|
|
535
|
-
stdoutLen: stdout.length,
|
|
536
|
-
stderrLen: stderr.length,
|
|
537
|
-
stderrTail: stderr.slice(-1e3)
|
|
538
|
-
});
|
|
539
|
-
resolve21(result);
|
|
540
|
-
});
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
async function checkAgentAuth(agent) {
|
|
544
|
-
const binary = resolveBinary(agent);
|
|
545
|
-
const binaryExists2 = await new Promise((resolve21) => {
|
|
546
|
-
if (binary.startsWith("/")) {
|
|
547
|
-
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() => resolve21(true), () => resolve21(false)));
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
const child = spawn(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
|
|
551
|
-
child.on("close", (code) => resolve21(code === 0));
|
|
552
|
-
});
|
|
553
|
-
if (!binaryExists2)
|
|
554
|
-
return "not-found";
|
|
555
|
-
if (agent !== "claude")
|
|
556
|
-
return "ok";
|
|
557
|
-
return new Promise((resolve21) => {
|
|
558
|
-
const child = spawn(binary, ["auth", "status", "--json"], {
|
|
559
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
560
|
-
});
|
|
561
|
-
let stdout = "";
|
|
562
|
-
let done = false;
|
|
563
|
-
const timer = setTimeout(() => {
|
|
564
|
-
if (!done) {
|
|
565
|
-
done = true;
|
|
566
|
-
child.kill("SIGTERM");
|
|
567
|
-
resolve21("unauthenticated");
|
|
568
|
-
}
|
|
569
|
-
}, 5e3);
|
|
570
|
-
child.stdout?.on("data", (chunk) => {
|
|
571
|
-
stdout += chunk.toString();
|
|
572
|
-
});
|
|
573
|
-
child.on("close", (code) => {
|
|
574
|
-
if (done)
|
|
575
|
-
return;
|
|
576
|
-
done = true;
|
|
577
|
-
clearTimeout(timer);
|
|
578
|
-
if (code !== 0) {
|
|
579
|
-
resolve21("unauthenticated");
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
try {
|
|
583
|
-
const status = JSON.parse(stdout);
|
|
584
|
-
resolve21(status.loggedIn ? "ok" : "unauthenticated");
|
|
585
|
-
} catch {
|
|
586
|
-
resolve21("unauthenticated");
|
|
587
|
-
}
|
|
588
|
-
});
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
function describeAgentFailure(result, maxDetail = 800) {
|
|
592
|
-
const base = result.exitCode !== 0 ? `agent exited with code ${result.exitCode}` : "agent produced no tool calls";
|
|
593
|
-
const detail = (result.stderr.trim() || result.stdout.trim()).slice(-maxDetail).trim();
|
|
594
|
-
return detail ? `${base} \u2014 ${detail}` : base;
|
|
595
|
-
}
|
|
596
|
-
function extractSentinelOutput(stdout) {
|
|
597
|
-
const START = "<<<EDS_OUTPUT_START>>>";
|
|
598
|
-
const END = "<<<EDS_OUTPUT_END>>>";
|
|
599
|
-
const startIdx = stdout.indexOf(START);
|
|
600
|
-
const endIdx = stdout.indexOf(END);
|
|
601
|
-
if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx)
|
|
602
|
-
return null;
|
|
603
|
-
const secondStart = stdout.indexOf(START, startIdx + START.length);
|
|
604
|
-
if (secondStart !== -1 && secondStart < endIdx)
|
|
605
|
-
return "multiple";
|
|
606
|
-
const afterStart = stdout.indexOf(END, startIdx);
|
|
607
|
-
const secondEnd = stdout.indexOf(END, afterStart + END.length);
|
|
608
|
-
if (secondEnd !== -1)
|
|
609
|
-
return "multiple";
|
|
610
|
-
return stdout.slice(startIdx + START.length, endIdx).trim();
|
|
611
|
-
}
|
|
612
|
-
var VALID_SELECT_TOOL_NAMES, VALID_TOOL_NAMES, VALID_TOKEN_TOOL_NAMES, VALID_CDF_TYPES, VALID_CATEGORIES, AGENT_BINARIES, BEDROCK_ENV_BY_AGENT, BEDROCK_CAPABLE_AGENTS, DEFAULT_CODEX_BEDROCK_REGION, DEFAULT_OPENCODE_MODEL, DEFAULT_MODELS, DEFAULT_CODEX_BEDROCK_MODEL;
|
|
613
|
-
var init_agent_runner = __esm({
|
|
614
|
-
"packages/experience-design-system-generation/dist/src/agent-runner.js"() {
|
|
748
|
+
var init_components = __esm({
|
|
749
|
+
"packages/experience-design-system-generation/dist/src/generate/services/preambles/components.js"() {
|
|
615
750
|
"use strict";
|
|
616
|
-
init_agent_names();
|
|
617
|
-
VALID_SELECT_TOOL_NAMES = /* @__PURE__ */ new Set(["select_component", "reject_component"]);
|
|
618
|
-
VALID_TOOL_NAMES = /* @__PURE__ */ new Set(["classify_prop", "exclude_prop", "classify_component", "classify_slot"]);
|
|
619
|
-
VALID_TOKEN_TOOL_NAMES = /* @__PURE__ */ new Set(["set_token", "set_group"]);
|
|
620
|
-
VALID_CDF_TYPES = /* @__PURE__ */ new Set(["string", "richtext", "media", "enum", "token", "boolean"]);
|
|
621
|
-
VALID_CATEGORIES = /* @__PURE__ */ new Set(["content", "design", "state"]);
|
|
622
|
-
AGENT_BINARIES = {
|
|
623
|
-
claude: "claude",
|
|
624
|
-
codex: "codex",
|
|
625
|
-
opencode: "opencode",
|
|
626
|
-
cursor: "cursor-agent",
|
|
627
|
-
copilot: "copilot"
|
|
628
|
-
};
|
|
629
|
-
BEDROCK_ENV_BY_AGENT = {
|
|
630
|
-
claude: { CLAUDE_CODE_USE_BEDROCK: "1" }
|
|
631
|
-
};
|
|
632
|
-
BEDROCK_CAPABLE_AGENTS = /* @__PURE__ */ new Set(["claude", "codex", "opencode"]);
|
|
633
|
-
DEFAULT_CODEX_BEDROCK_REGION = "us-east-1";
|
|
634
|
-
DEFAULT_OPENCODE_MODEL = "claude-haiku-4-5";
|
|
635
|
-
DEFAULT_MODELS = {
|
|
636
|
-
claude: "haiku",
|
|
637
|
-
opencode: DEFAULT_OPENCODE_MODEL,
|
|
638
|
-
cursor: "gpt-mini",
|
|
639
|
-
// cursor alias for gpt-5.4-mini-medium; haiku not in cursor's catalog
|
|
640
|
-
copilot: "Auto"
|
|
641
|
-
// the only model guaranteed on every Copilot plan (Free/Pro/Business/Enterprise); Pro+ users override via EDS_AGENT_MODEL_COPILOT
|
|
642
|
-
};
|
|
643
|
-
DEFAULT_CODEX_BEDROCK_MODEL = "openai.gpt-5.6-luna";
|
|
644
751
|
}
|
|
645
752
|
});
|
|
646
753
|
|
|
647
|
-
// packages/experience-design-system-generation/dist/src/
|
|
648
|
-
function
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
754
|
+
// packages/experience-design-system-generation/dist/src/generate/services/preambles/map-tokens.js
|
|
755
|
+
function buildMapTokensAutonomousPreamble(inputBlock) {
|
|
756
|
+
return `You are running as part of the experience-design-system-cli generate pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
|
|
757
|
+
|
|
758
|
+
Context: The components below already have design-category, token-typed props (\`$token.kind\` set). Your task is to decide, from source evidence, whether to narrow each one to a restricted subset (\`token_allowed\`) of the tokens matching its \`$token.kind\`. Apply all judgment calls yourself \u2014 do not pause to ask for confirmation.
|
|
759
|
+
|
|
760
|
+
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
761
|
+
|
|
762
|
+
## Output protocol
|
|
763
|
+
|
|
764
|
+
Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object per line to stdout for each prop you narrow. The CLI reads your stdout line by line and writes each decision directly to the pipeline database.
|
|
765
|
+
|
|
766
|
+
The one tool call you may emit:
|
|
767
|
+
|
|
768
|
+
\`\`\`
|
|
769
|
+
{"tool":"map_token_prop","component":"<ComponentName>","prop":"<propName>","token_allowed":["colors.brand.primary","colors.brand.secondary"]}
|
|
770
|
+
\`\`\`
|
|
771
|
+
|
|
772
|
+
Rules:
|
|
773
|
+
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences around the lines.
|
|
774
|
+
- Only emit a call for a prop that appears in the "Generated CDF so far" section.
|
|
775
|
+
- Each "Token path index" section below is already scoped to one \`$token.kind\` \u2014 a prop only draws candidates from the section matching its own \`$token.kind\` (or the "full tree" section, for a prop with no \`$token.kind\`). Never cross sections, never emit a group/prefix path, and never invent a path \u2014 every entry in \`token_allowed\` must exist verbatim in the matching section.
|
|
776
|
+
- \`token_allowed\` is required and must be non-empty when the call is emitted.
|
|
777
|
+
- For the judgment call of whether a prop should be narrowed at all, follow the decision tree in the map-tokens skill file: it explains defaults vs. restrictions, misclassified variant-name props, and when to emit nothing.
|
|
778
|
+
- You may emit prose lines (not starting with \`{\`) anywhere \u2014 they are ignored by the parser and serve as your reasoning log.`;
|
|
658
779
|
}
|
|
659
|
-
var
|
|
660
|
-
"packages/experience-design-system-generation/dist/src/
|
|
780
|
+
var init_map_tokens = __esm({
|
|
781
|
+
"packages/experience-design-system-generation/dist/src/generate/services/preambles/map-tokens.js"() {
|
|
661
782
|
"use strict";
|
|
662
|
-
init_agent_runner();
|
|
663
783
|
}
|
|
664
784
|
});
|
|
665
785
|
|
|
666
|
-
// packages/experience-design-system-generation/dist/src/
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
import { dirname, join as join2, resolve } from "node:path";
|
|
670
|
-
import { fileURLToPath } from "node:url";
|
|
671
|
-
import { flattenDTCG } from "@contentful/experience-design-system-types";
|
|
672
|
-
function formatCustomPromptBanner(skill, path) {
|
|
673
|
-
return `WARNING: Custom prompt active for ${skill}: ${path}
|
|
674
|
-
Bundled invariants (utility-wrapper rejection, description content rules) do NOT apply.
|
|
675
|
-
You are responsible for the prompt's correctness.
|
|
676
|
-
`;
|
|
677
|
-
}
|
|
678
|
-
async function buildPrompt(options) {
|
|
679
|
-
const skillContent = options.skillContentOverride ?? await readSkillFile(options.skill, options.skillPathOverride);
|
|
680
|
-
const preamble = buildPreamble(options);
|
|
681
|
-
return `${preamble}
|
|
786
|
+
// packages/experience-design-system-generation/dist/src/generate/services/preambles/select.js
|
|
787
|
+
function buildSelectAutonomousPreamble(inputBlock) {
|
|
788
|
+
return `You are running as part of the experience-design-system-cli import pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
|
|
682
789
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
790
|
+
Your task: review the components provided below and decide whether each belongs in Contentful Experience Orchestration as a Component Type. The input is a JSON array \u2014 you may receive 1\u2013N components in a single message. Emit one tool call per input component, named after the component. Apply all judgment calls yourself \u2014 do not pause to ask for confirmation. Include a brief "reason" to document your reasoning for each decision.
|
|
791
|
+
|
|
792
|
+
Key rule: accept any component that renders visible UI \u2014 atoms, molecules, and organisms are all valid Component Types in Contentful Experience Orchestration. Reject only components that produce zero visual output: React hooks, pure context providers, A/B testing or variant-routing wrappers, analytics trackers, and security utilities. Do NOT reject a component because it has few props, is low-level, or has some A/B testing or personalization-related props mixed in \u2014 those props are handled in the generate step.
|
|
793
|
+
|
|
794
|
+
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
795
|
+
|
|
796
|
+
## Output protocol
|
|
797
|
+
|
|
798
|
+
Do NOT write any files or emit any JSON blobs. Instead, emit JSON tool calls one per line to stdout. The CLI reads your stdout line by line.
|
|
799
|
+
|
|
800
|
+
The two tool calls \u2014 emit exactly one per input component:
|
|
801
|
+
|
|
802
|
+
\`\`\`
|
|
803
|
+
{"tool":"select_component","name":"<ComponentName>","reason":"<brief reason>"}
|
|
804
|
+
|
|
805
|
+
{"tool":"reject_component","name":"<ComponentName>","reason":"<brief reason>"}
|
|
806
|
+
\`\`\`
|
|
807
|
+
|
|
808
|
+
Rules:
|
|
809
|
+
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences.
|
|
810
|
+
- Emit exactly one tool call per input component. The "name" field must match a component name from the input array exactly. Tool calls may appear in any order.
|
|
811
|
+
- You may emit prose lines (not starting with {) to reason before each tool call \u2014 they are ignored by the parser.`;
|
|
686
812
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
691
|
-
let dir = thisDir;
|
|
692
|
-
for (; ; ) {
|
|
693
|
-
const candidate = join2(dir, "skills");
|
|
694
|
-
if (existsSync(candidate))
|
|
695
|
-
return join2(candidate, SKILL_FILES[skill]);
|
|
696
|
-
const parent = resolve(dir, "..");
|
|
697
|
-
if (parent === dir) {
|
|
698
|
-
throw new Error(`skill file missing from CLI installation (could not locate skills/ directory from: ${thisDir})`);
|
|
699
|
-
}
|
|
700
|
-
dir = parent;
|
|
813
|
+
var init_select = __esm({
|
|
814
|
+
"packages/experience-design-system-generation/dist/src/generate/services/preambles/select.js"() {
|
|
815
|
+
"use strict";
|
|
701
816
|
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
// packages/experience-design-system-generation/dist/src/generate/services/preambles/tokens.js
|
|
820
|
+
function buildTokensAutonomousPreamble(inputBlock) {
|
|
821
|
+
return `You are running as part of the experience-design-system-cli generate pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
|
|
822
|
+
|
|
823
|
+
Your task: classify every raw token from the input below into a DTCG token tree. Apply all judgment calls yourself \u2014 do not pause to ask for confirmation. Include a "description" field on each set_token call to document your reasoning.
|
|
824
|
+
|
|
825
|
+
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
826
|
+
|
|
827
|
+
## Output protocol
|
|
828
|
+
|
|
829
|
+
Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object per line to stdout for each token or group. The CLI reads your stdout line by line and writes each entry directly to the pipeline database.
|
|
830
|
+
|
|
831
|
+
The two tool calls you may emit are:
|
|
832
|
+
|
|
833
|
+
\`\`\`
|
|
834
|
+
{"tool":"set_group","path":"<dot.notation.path>","description":"<optional group description>"}
|
|
835
|
+
|
|
836
|
+
{"tool":"set_token","path":"<dot.notation.path>","type":"<DTCG type>","value":<value>,"description":"<reason>"}
|
|
837
|
+
\`\`\`
|
|
838
|
+
|
|
839
|
+
Rules:
|
|
840
|
+
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences.
|
|
841
|
+
- Emit a set_group call for every intermediate group node in the tree.
|
|
842
|
+
- Emit a set_token call for every leaf token.
|
|
843
|
+
- "path" is dot-notation, e.g. "colors.brand.primary" \u2014 no leading dots or slashes.
|
|
844
|
+
- "type" must be one of the 13 valid DTCG types: color, dimension, fontFamily, fontWeight, duration, cubicBezier, number, strokeStyle, border, transition, shadow, gradient, typography.
|
|
845
|
+
- "value" must be valid JSON (string, number, array, or object depending on the type). Do NOT wrap it in quotes if it is a complex type.
|
|
846
|
+
- Emit set_group calls before the set_token calls that fall under them.
|
|
847
|
+
- You may emit prose lines (not starting with {) anywhere \u2014 they are ignored by the parser and serve as your reasoning log.`;
|
|
848
|
+
}
|
|
849
|
+
var init_tokens = __esm({
|
|
850
|
+
"packages/experience-design-system-generation/dist/src/generate/services/preambles/tokens.js"() {
|
|
851
|
+
"use strict";
|
|
711
852
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
// packages/experience-design-system-generation/dist/src/generate/services/preambles/index.js
|
|
856
|
+
var init_preambles = __esm({
|
|
857
|
+
"packages/experience-design-system-generation/dist/src/generate/services/preambles/index.js"() {
|
|
858
|
+
"use strict";
|
|
859
|
+
init_components();
|
|
860
|
+
init_map_tokens();
|
|
861
|
+
init_select();
|
|
862
|
+
init_tokens();
|
|
717
863
|
}
|
|
718
|
-
}
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
// packages/experience-design-system-generation/dist/src/generate/services/prompt-context-service.js
|
|
867
|
+
import { flattenDTCG } from "@contentful/experience-design-system-types";
|
|
719
868
|
function inferFenceLang(filename) {
|
|
720
869
|
if (!filename)
|
|
721
870
|
return "json";
|
|
@@ -775,7 +924,7 @@ function renderTokenCandidateSection(kind, entries) {
|
|
|
775
924
|
return `${label}, one leaf token per line as \`path \xB7 type\`, no \`$value\`:
|
|
776
925
|
${formatTokenCandidateLines(entries)}`;
|
|
777
926
|
}
|
|
778
|
-
function
|
|
927
|
+
function renderPromptContext(options) {
|
|
779
928
|
const { skill, rawComponentsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs, existingComponentsInline, existingTokensInline, componentAllowlistInline } = options;
|
|
780
929
|
const sections = [];
|
|
781
930
|
if (existingComponentsInline) {
|
|
@@ -791,7 +940,7 @@ ${existingTokensInline}
|
|
|
791
940
|
\`\`\``);
|
|
792
941
|
}
|
|
793
942
|
if (componentAllowlistInline) {
|
|
794
|
-
sections.push(`Known component names for slot allowed_components (hard allowlist; never use any other name)
|
|
943
|
+
sections.push(`Known component names for slot allowed_components (hard allowlist; never use any other name). Never invent a child from an import, JSX element, type name, icon name, or implementation helper.
|
|
795
944
|
\`\`\`json
|
|
796
945
|
${componentAllowlistInline}
|
|
797
946
|
\`\`\``);
|
|
@@ -881,149 +1030,56 @@ ${JSON.stringify(withoutContent.map((ref) => ({ component: ref.component, source
|
|
|
881
1030
|
\`\`\``);
|
|
882
1031
|
}
|
|
883
1032
|
}
|
|
884
|
-
|
|
1033
|
+
return sections.length > 0 ? `
|
|
885
1034
|
|
|
886
1035
|
${sections.join("\n\n")}` : "";
|
|
887
|
-
if (skill === "components") {
|
|
888
|
-
return buildComponentsAutonomousPreamble(inputBlock);
|
|
889
|
-
}
|
|
890
|
-
if (skill === "select") {
|
|
891
|
-
return buildSelectAutonomousPreamble(inputBlock);
|
|
892
|
-
}
|
|
893
|
-
if (skill === "map-tokens") {
|
|
894
|
-
return buildMapTokensAutonomousPreamble(inputBlock);
|
|
895
|
-
}
|
|
896
|
-
return buildTokensAutonomousPreamble(inputBlock);
|
|
897
|
-
}
|
|
898
|
-
function buildComponentsAutonomousPreamble(inputBlock) {
|
|
899
|
-
return `You are running as part of the experience-design-system-cli generate pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
|
|
900
|
-
|
|
901
|
-
Context: You are classifying a React component for **Contentful Experience Orchestration**. The result is a Component Type \u2014 a schema that tells Contentful what a marketer can configure. Properties fall into three categories:
|
|
902
|
-
- **design**: controls how the component looks (variant, size, color, layout toggles)
|
|
903
|
-
- **content**: the data a content editor fills in (text, images, URLs, rich text)
|
|
904
|
-
- **state**: runtime behavioral flags (disabled, loading, expanded, identifiers)
|
|
905
|
-
|
|
906
|
-
Your task: classify every prop and slot in the component below. Apply all judgment calls yourself \u2014 do not pause to ask for confirmation. Include a "description" field on each tool call to document your reasoning so the developer can review it afterward.
|
|
907
|
-
|
|
908
|
-
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
909
|
-
|
|
910
|
-
## Output protocol
|
|
911
|
-
|
|
912
|
-
Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object per line to stdout for each classification decision. The CLI reads your stdout line by line and writes each decision directly to the pipeline database.
|
|
913
|
-
|
|
914
|
-
The four tool calls you may emit are:
|
|
915
|
-
|
|
916
|
-
\`\`\`
|
|
917
|
-
{"tool":"classify_component","description":"<optional component-level description>","rationale":{"description":"<why this component is classified the way it is>","props":"<why these props were chosen>","slots":"<why these slots were chosen>"}}
|
|
918
|
-
|
|
919
|
-
{"tool":"classify_prop","prop":"<propName>","cdf_type":"<type>","cdf_category":"<category>","required":<bool>,"description":"<short customer-facing description>","reason":"<full internal rationale; not customer-facing>","values":["a","b"],"token_kind":"color","default":"<value>"}
|
|
920
|
-
|
|
921
|
-
{"tool":"exclude_prop","prop":"<propName>","reason":"<why excluded>"}
|
|
922
|
-
|
|
923
|
-
{"tool":"classify_slot","slot":"<slotName>","required":<bool>,"allowed_components":["ComponentName"],"description":"<reason>","rationale":"<why this slot was kept in the catalog>"}
|
|
924
|
-
\`\`\`
|
|
925
|
-
|
|
926
|
-
Rules:
|
|
927
|
-
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences around the lines.
|
|
928
|
-
- Every prop in the input must have exactly one call: either classify_prop or exclude_prop.
|
|
929
|
-
- Every slot in the input must have exactly one classify_slot call.
|
|
930
|
-
- Valid cdf_type values: string, richtext, media, enum, token, boolean
|
|
931
|
-
- Valid cdf_category values: content, design, state
|
|
932
|
-
- For enum type, always include \`values\` (non-empty string array of the variant names the prop accepts).
|
|
933
|
-
- For token type, always include \`token_kind\` (DTCG $type, e.g. "color"). **Never emit \`values\` for \`cdf_type: "token"\` props** \u2014 an enum prop's list holds variant names; a token prop's list holds design token paths, produced separately and never by you. Emitting \`values\` on a token prop makes the definition invalid.
|
|
934
|
-
- Never emit both "values" and "token_kind" on one prop.
|
|
935
|
-
- \`enum\` vs \`token\` is decided by three questions answered in order from the source shown \u2014 never from the TypeScript type. Q1: does the component look the value up, switch on it, or have a vocabulary for it (\`tokens[x]\`, \`switch (variant)\`, \`allowedValues\`)? yes \u2192 \`enum\`, stop.
|
|
936
|
-
- Q2: is the value written straight into a style or attribute (\`rx={radius}\`, \`padding: \${padding}\`)? no \u2192 not \`token\`, apply the type rules.
|
|
937
|
-
- Q3: is there a design-token reference at that use \u2014 a \`tokens.*\` parameter default, a \`tokenReference\`, an inline \`tokens.*\` / \`var(--*)\`? yes \u2192 \`token\` (cite both lines in "reason"); no \u2192 \`string\`. "Ambiguity resolves to \`enum\`" applies only when Q1\u2013Q3 cannot be answered from the source shown.
|
|
938
|
-
- CSS design props (className, style, styles, positional/geometric props: top, bottom, left, right, rotation, offset, etc.) \u2192 classify_prop, cdf_type: "string", cdf_category: "design".
|
|
939
|
-
- For \`classify_slot.allowed_components\`, use only exact names from the hard allowlist provided below. Never invent a child from an import, JSX element, type name, icon name, or implementation helper; if a child is not listed, omit it.
|
|
940
|
-
- On classify_component, "rationale" fields are operator-facing (read-only) but may surface in customer-facing exports. The "rationale.description" field is subject to the description content rules in the skill prompt (no internal initiative names). "rationale.props" and "rationale.slots" describe your reasoning about scope; "classify_slot.rationale" explains why each slot was kept.
|
|
941
|
-
- On classify_prop, "reason" is REQUIRED and is the LLM's internal rationale \u2014 shown to the developer reviewing the import, never to end-users. "description" is the customer-facing copy and is subject to the description content rules in the skill prompt. Keep them distinct: "description" is short and customer-facing; "reason" explains your reasoning in detail.
|
|
942
|
-
- You may emit prose lines (not starting with {) anywhere \u2014 they are ignored by the parser and serve as your reasoning log.`;
|
|
943
|
-
}
|
|
944
|
-
function buildSelectAutonomousPreamble(inputBlock) {
|
|
945
|
-
return `You are running as part of the experience-design-system-cli import pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
|
|
946
|
-
|
|
947
|
-
Your task: review the components provided below and decide whether each belongs in Contentful Experience Orchestration as a Component Type. The input is a JSON array \u2014 you may receive 1\u2013N components in a single message. Emit one tool call per input component, named after the component. Apply all judgment calls yourself \u2014 do not pause to ask for confirmation. Include a brief "reason" to document your reasoning for each decision.
|
|
948
|
-
|
|
949
|
-
Key rule: accept any component that renders visible UI \u2014 atoms, molecules, and organisms are all valid Component Types in Contentful Experience Orchestration. Reject only components that produce zero visual output: React hooks, pure context providers, A/B testing or variant-routing wrappers, analytics trackers, and security utilities. Do NOT reject a component because it has few props, is low-level, or has some A/B testing or personalization-related props mixed in \u2014 those props are handled in the generate step.
|
|
950
|
-
|
|
951
|
-
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
952
|
-
|
|
953
|
-
## Output protocol
|
|
954
|
-
|
|
955
|
-
Do NOT write any files or emit any JSON blobs. Instead, emit JSON tool calls one per line to stdout. The CLI reads your stdout line by line.
|
|
956
|
-
|
|
957
|
-
The two tool calls \u2014 emit exactly one per input component:
|
|
958
|
-
|
|
959
|
-
\`\`\`
|
|
960
|
-
{"tool":"select_component","name":"<ComponentName>","reason":"<brief reason>"}
|
|
961
|
-
|
|
962
|
-
{"tool":"reject_component","name":"<ComponentName>","reason":"<brief reason>"}
|
|
963
|
-
\`\`\`
|
|
964
|
-
|
|
965
|
-
Rules:
|
|
966
|
-
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences.
|
|
967
|
-
- Emit exactly one tool call per input component. The "name" field must match a component name from the input array exactly. Tool calls may appear in any order.
|
|
968
|
-
- You may emit prose lines (not starting with {) to reason before each tool call \u2014 they are ignored by the parser.`;
|
|
969
1036
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
976
|
-
|
|
977
|
-
## Output protocol
|
|
978
|
-
|
|
979
|
-
Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object per line to stdout for each prop you narrow. The CLI reads your stdout line by line and writes each decision directly to the pipeline database.
|
|
980
|
-
|
|
981
|
-
The one tool call you may emit:
|
|
982
|
-
|
|
983
|
-
\`\`\`
|
|
984
|
-
{"tool":"map_token_prop","component":"<ComponentName>","prop":"<propName>","token_allowed":["colors.brand.primary","colors.brand.secondary"]}
|
|
985
|
-
\`\`\`
|
|
1037
|
+
var init_prompt_context_service = __esm({
|
|
1038
|
+
"packages/experience-design-system-generation/dist/src/generate/services/prompt-context-service.js"() {
|
|
1039
|
+
"use strict";
|
|
1040
|
+
}
|
|
1041
|
+
});
|
|
986
1042
|
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1043
|
+
// packages/experience-design-system-generation/dist/src/generate/services/skill-loader.js
|
|
1044
|
+
import { existsSync } from "node:fs";
|
|
1045
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
1046
|
+
import { dirname, join as join2, resolve } from "node:path";
|
|
1047
|
+
import { fileURLToPath } from "node:url";
|
|
1048
|
+
function resolveSkillPath(skill) {
|
|
1049
|
+
if (!(skill in SKILL_FILES))
|
|
1050
|
+
throw new Error(`Invalid skill: ${skill}`);
|
|
1051
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
1052
|
+
let dir = thisDir;
|
|
1053
|
+
for (; ; ) {
|
|
1054
|
+
const candidate = join2(dir, "skills");
|
|
1055
|
+
if (existsSync(candidate))
|
|
1056
|
+
return join2(candidate, SKILL_FILES[skill]);
|
|
1057
|
+
const parent = resolve(dir, "..");
|
|
1058
|
+
if (parent === dir) {
|
|
1059
|
+
throw new Error(`skill file missing from CLI installation (could not locate skills/ directory from: ${thisDir})`);
|
|
1060
|
+
}
|
|
1061
|
+
dir = parent;
|
|
1062
|
+
}
|
|
994
1063
|
}
|
|
995
|
-
function
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
{"tool":"set_token","path":"<dot.notation.path>","type":"<DTCG type>","value":<value>,"description":"<reason>"}
|
|
1012
|
-
\`\`\`
|
|
1013
|
-
|
|
1014
|
-
Rules:
|
|
1015
|
-
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences.
|
|
1016
|
-
- Emit a set_group call for every intermediate group node in the tree.
|
|
1017
|
-
- Emit a set_token call for every leaf token.
|
|
1018
|
-
- "path" is dot-notation, e.g. "colors.brand.primary" \u2014 no leading dots or slashes.
|
|
1019
|
-
- "type" must be one of the 13 valid DTCG types: color, dimension, fontFamily, fontWeight, duration, cubicBezier, number, strokeStyle, border, transition, shadow, gradient, typography.
|
|
1020
|
-
- "value" must be valid JSON (string, number, array, or object depending on the type). Do NOT wrap it in quotes if it is a complex type.
|
|
1021
|
-
- Emit set_group calls before the set_token calls that fall under them.
|
|
1022
|
-
- You may emit prose lines (not starting with {) anywhere \u2014 they are ignored by the parser and serve as your reasoning log.`;
|
|
1064
|
+
async function loadSkillContent(skill, override) {
|
|
1065
|
+
if (override) {
|
|
1066
|
+
const skillPath2 = resolve(override);
|
|
1067
|
+
try {
|
|
1068
|
+
return await readFile2(skillPath2, "utf8");
|
|
1069
|
+
} catch {
|
|
1070
|
+
throw new Error(`custom prompt file not found (skill: ${skill}, path: ${skillPath2})`);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
const skillPath = resolveSkillPath(skill);
|
|
1074
|
+
try {
|
|
1075
|
+
return await readFile2(skillPath, "utf8");
|
|
1076
|
+
} catch {
|
|
1077
|
+
throw new Error(`skill file missing from CLI installation \u2014 try reinstalling the CLI (looked for: ${skillPath})`);
|
|
1078
|
+
}
|
|
1023
1079
|
}
|
|
1024
1080
|
var SKILL_FILES;
|
|
1025
|
-
var
|
|
1026
|
-
"packages/experience-design-system-generation/dist/src/
|
|
1081
|
+
var init_skill_loader = __esm({
|
|
1082
|
+
"packages/experience-design-system-generation/dist/src/generate/services/skill-loader.js"() {
|
|
1027
1083
|
"use strict";
|
|
1028
1084
|
SKILL_FILES = {
|
|
1029
1085
|
components: "generate-components.md",
|
|
@@ -1034,13 +1090,131 @@ var init_prompt_builder = __esm({
|
|
|
1034
1090
|
}
|
|
1035
1091
|
});
|
|
1036
1092
|
|
|
1037
|
-
// packages/experience-design-system-generation/dist/src/
|
|
1093
|
+
// packages/experience-design-system-generation/dist/src/generate/services/prompt-service.js
|
|
1094
|
+
function formatCustomPromptBanner(skill, path) {
|
|
1095
|
+
return `WARNING: Custom prompt active for ${skill}: ${path}
|
|
1096
|
+
Bundled invariants (utility-wrapper rejection, description content rules) do NOT apply.
|
|
1097
|
+
You are responsible for the prompt's correctness.
|
|
1098
|
+
`;
|
|
1099
|
+
}
|
|
1100
|
+
async function buildPrompt(options) {
|
|
1101
|
+
const skillContent = options.skillContentOverride ?? await loadSkillContent(options.skill, options.skillPathOverride);
|
|
1102
|
+
const preamble = buildPreamble(options);
|
|
1103
|
+
return `${preamble}
|
|
1104
|
+
|
|
1105
|
+
Skill instructions follow:
|
|
1106
|
+
---
|
|
1107
|
+
${skillContent}`;
|
|
1108
|
+
}
|
|
1109
|
+
function buildPreamble(options) {
|
|
1110
|
+
const inputBlock = renderPromptContext(options);
|
|
1111
|
+
switch (options.skill) {
|
|
1112
|
+
case "components":
|
|
1113
|
+
return buildComponentsAutonomousPreamble(inputBlock);
|
|
1114
|
+
case "select":
|
|
1115
|
+
return buildSelectAutonomousPreamble(inputBlock);
|
|
1116
|
+
case "map-tokens":
|
|
1117
|
+
return buildMapTokensAutonomousPreamble(inputBlock);
|
|
1118
|
+
case "tokens":
|
|
1119
|
+
return buildTokensAutonomousPreamble(inputBlock);
|
|
1120
|
+
default:
|
|
1121
|
+
return buildTokensAutonomousPreamble(inputBlock);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
var init_prompt_service = __esm({
|
|
1125
|
+
"packages/experience-design-system-generation/dist/src/generate/services/prompt-service.js"() {
|
|
1126
|
+
"use strict";
|
|
1127
|
+
init_preambles();
|
|
1128
|
+
init_prompt_context_service();
|
|
1129
|
+
init_skill_loader();
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
// packages/experience-design-system-generation/dist/src/generate/services/progress-service.js
|
|
1038
1134
|
function formatGenerateProgressLine(done, total, name) {
|
|
1039
1135
|
return `progress=generate:${done}/${total}:${name}`;
|
|
1040
1136
|
}
|
|
1041
|
-
var
|
|
1042
|
-
"packages/experience-design-system-generation/dist/src/progress.js"() {
|
|
1137
|
+
var init_progress_service = __esm({
|
|
1138
|
+
"packages/experience-design-system-generation/dist/src/generate/services/progress-service.js"() {
|
|
1139
|
+
"use strict";
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1142
|
+
|
|
1143
|
+
// packages/experience-design-system-generation/dist/src/generate/model/errors.js
|
|
1144
|
+
var GenerateRequestError;
|
|
1145
|
+
var init_errors = __esm({
|
|
1146
|
+
"packages/experience-design-system-generation/dist/src/generate/model/errors.js"() {
|
|
1043
1147
|
"use strict";
|
|
1148
|
+
GenerateRequestError = class extends Error {
|
|
1149
|
+
reason;
|
|
1150
|
+
stage;
|
|
1151
|
+
constructor(reason, stage) {
|
|
1152
|
+
super(`unsupported generation stage '${String(stage)}'`);
|
|
1153
|
+
this.name = "GenerateRequestError";
|
|
1154
|
+
this.reason = reason;
|
|
1155
|
+
this.stage = stage;
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
});
|
|
1160
|
+
|
|
1161
|
+
// packages/experience-design-system-generation/dist/src/generate/controller/generate-endpoint.js
|
|
1162
|
+
function createGenerateEndpoint(dependencies) {
|
|
1163
|
+
const promptService = dependencies.promptService ?? defaultPromptService;
|
|
1164
|
+
const protocolParser = dependencies.protocolParser ?? defaultProtocolParser;
|
|
1165
|
+
const getFailure = dependencies.describeFailure ?? describeAgentFailure;
|
|
1166
|
+
const stageParsers = {
|
|
1167
|
+
components: protocolParser.parseComponents,
|
|
1168
|
+
tokens: protocolParser.parseTokens,
|
|
1169
|
+
select: protocolParser.parseSelect,
|
|
1170
|
+
"map-tokens": protocolParser.parseMapTokens
|
|
1171
|
+
};
|
|
1172
|
+
function requireStage(request2) {
|
|
1173
|
+
const stage = request2.prompt.skill;
|
|
1174
|
+
if (!Object.hasOwn(stageParsers, stage))
|
|
1175
|
+
throw new GenerateRequestError("unknown-stage", stage);
|
|
1176
|
+
return stage;
|
|
1177
|
+
}
|
|
1178
|
+
return {
|
|
1179
|
+
async execute(request2) {
|
|
1180
|
+
const stage = requireStage(request2);
|
|
1181
|
+
const prompt = await promptService.buildPrompt(request2.prompt);
|
|
1182
|
+
const run = await dependencies.invoker.invoke({ ...request2.invocation, prompt });
|
|
1183
|
+
const { calls, warnings } = stageParsers[stage](run.stdout);
|
|
1184
|
+
const failure = getRunFailure(run, stage, calls.length, getFailure);
|
|
1185
|
+
return { stage, prompt, run, calls, warnings, ...failure ? { failure } : {} };
|
|
1186
|
+
},
|
|
1187
|
+
async preview(request2) {
|
|
1188
|
+
const stage = requireStage(request2);
|
|
1189
|
+
return { stage, prompt: await promptService.buildPrompt(request2.prompt) };
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
function getRunFailure(run, stage, callCount, describeFailure) {
|
|
1194
|
+
if (run.timedOut)
|
|
1195
|
+
return "agent timed out";
|
|
1196
|
+
if (run.exitCode !== 0)
|
|
1197
|
+
return describeFailure(run);
|
|
1198
|
+
if (callCount === 0 && !STAGES_WITH_OPTIONAL_CALLS.has(stage))
|
|
1199
|
+
return describeFailure(run);
|
|
1200
|
+
return void 0;
|
|
1201
|
+
}
|
|
1202
|
+
var defaultPromptService, defaultProtocolParser, STAGES_WITH_OPTIONAL_CALLS;
|
|
1203
|
+
var init_generate_endpoint = __esm({
|
|
1204
|
+
"packages/experience-design-system-generation/dist/src/generate/controller/generate-endpoint.js"() {
|
|
1205
|
+
"use strict";
|
|
1206
|
+
init_errors();
|
|
1207
|
+
init_failure_diagnostics_service();
|
|
1208
|
+
init_prompt_service();
|
|
1209
|
+
init_protocol_parser_service();
|
|
1210
|
+
defaultPromptService = { buildPrompt };
|
|
1211
|
+
defaultProtocolParser = {
|
|
1212
|
+
parseComponents: parseToolCallLines,
|
|
1213
|
+
parseTokens: parseTokenToolCallLines,
|
|
1214
|
+
parseSelect: parseSelectToolCallLines,
|
|
1215
|
+
parseMapTokens: parseMapTokenPropToolCallLines
|
|
1216
|
+
};
|
|
1217
|
+
STAGES_WITH_OPTIONAL_CALLS = /* @__PURE__ */ new Set(["map-tokens"]);
|
|
1044
1218
|
}
|
|
1045
1219
|
});
|
|
1046
1220
|
|
|
@@ -1049,10 +1223,12 @@ var src_exports = {};
|
|
|
1049
1223
|
__export(src_exports, {
|
|
1050
1224
|
AGENT_NAMES: () => AGENT_NAMES,
|
|
1051
1225
|
DEFAULT_AGENT_NAME: () => DEFAULT_AGENT_NAME,
|
|
1226
|
+
GenerateRequestError: () => GenerateRequestError,
|
|
1052
1227
|
agentSupportsBedrock: () => agentSupportsBedrock,
|
|
1053
1228
|
buildArgs: () => buildArgs,
|
|
1054
1229
|
buildPrompt: () => buildPrompt,
|
|
1055
1230
|
checkAgentAuth: () => checkAgentAuth,
|
|
1231
|
+
createGenerateEndpoint: () => createGenerateEndpoint,
|
|
1056
1232
|
createLocalCliAgentInvoker: () => createLocalCliAgentInvoker,
|
|
1057
1233
|
describeAgentFailure: () => describeAgentFailure,
|
|
1058
1234
|
extractSentinelOutput: () => extractSentinelOutput,
|
|
@@ -1071,11 +1247,18 @@ __export(src_exports, {
|
|
|
1071
1247
|
var init_src = __esm({
|
|
1072
1248
|
"packages/experience-design-system-generation/dist/src/index.js"() {
|
|
1073
1249
|
"use strict";
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1250
|
+
init_agent();
|
|
1251
|
+
init_agent_configuration_service();
|
|
1252
|
+
init_agent_auth_service();
|
|
1253
|
+
init_failure_diagnostics_service();
|
|
1254
|
+
init_local_agent_process();
|
|
1255
|
+
init_protocol_parser_service();
|
|
1256
|
+
init_local_agent_invoker();
|
|
1257
|
+
init_prompt_service();
|
|
1258
|
+
init_skill_loader();
|
|
1259
|
+
init_progress_service();
|
|
1260
|
+
init_generate_endpoint();
|
|
1261
|
+
init_errors();
|
|
1079
1262
|
}
|
|
1080
1263
|
});
|
|
1081
1264
|
|
|
@@ -1343,17 +1526,23 @@ var init_debug_logger = __esm({
|
|
|
1343
1526
|
});
|
|
1344
1527
|
|
|
1345
1528
|
// packages/experience-design-system-cli/src/lib/agent-output.ts
|
|
1346
|
-
|
|
1529
|
+
function createAgentOutputCapture(verbose) {
|
|
1347
1530
|
let output = "";
|
|
1348
1531
|
const formatter = new OutputFormatter(verbose, (chunk) => {
|
|
1349
1532
|
output += chunk;
|
|
1350
1533
|
});
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1534
|
+
return {
|
|
1535
|
+
onOutput: (chunk) => formatter.push(chunk),
|
|
1536
|
+
finish() {
|
|
1537
|
+
formatter.flush();
|
|
1538
|
+
return output;
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
async function invokeAgentWithOutput(invoker2, options, verbose) {
|
|
1543
|
+
const capture = createAgentOutputCapture(verbose);
|
|
1544
|
+
const result = await invoker2.invoke({ ...options, onOutput: capture.onOutput });
|
|
1545
|
+
return { result, output: capture.finish() };
|
|
1357
1546
|
}
|
|
1358
1547
|
var init_agent_output = __esm({
|
|
1359
1548
|
"packages/experience-design-system-cli/src/lib/agent-output.ts"() {
|
|
@@ -5082,7 +5271,7 @@ async function runOneComponent(options, component, index, total) {
|
|
|
5082
5271
|
component.props.map((p) => p.type)
|
|
5083
5272
|
);
|
|
5084
5273
|
const existingComponentsInline = existingContentfulEntities ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, component.name)) : void 0;
|
|
5085
|
-
const
|
|
5274
|
+
const promptOptions = {
|
|
5086
5275
|
skill: "components",
|
|
5087
5276
|
mode: "autonomous",
|
|
5088
5277
|
rawComponentsInline,
|
|
@@ -5096,20 +5285,22 @@ async function runOneComponent(options, component, index, total) {
|
|
|
5096
5285
|
existingComponentsInline,
|
|
5097
5286
|
existingTokensInline,
|
|
5098
5287
|
componentAllowlistInline: JSON.stringify([...allowedComponentNames2].sort())
|
|
5099
|
-
}
|
|
5288
|
+
};
|
|
5289
|
+
const endpoint = createGenerateEndpoint({ invoker });
|
|
5100
5290
|
const maxAttempts = 2;
|
|
5101
5291
|
let lastError = "";
|
|
5102
5292
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
5103
5293
|
if (attempt > 1) await new Promise((res) => setTimeout(res, RETRY_BACKOFF_MS));
|
|
5104
|
-
const
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
);
|
|
5294
|
+
const outputCapture = createAgentOutputCapture(verbose);
|
|
5295
|
+
const response = await endpoint.execute({
|
|
5296
|
+
prompt: promptOptions,
|
|
5297
|
+
invocation: { agent, model, timeoutMs: DEFAULT_TIMEOUT_MS, onOutput: outputCapture.onOutput }
|
|
5298
|
+
});
|
|
5299
|
+
const outputBuf = outputCapture.finish();
|
|
5109
5300
|
const retryNote = attempt > 1 ? ` ${c.yellow(`retrying (${attempt}/${maxAttempts})`)}` : "";
|
|
5110
5301
|
process.stderr.write(` ${pos} ${c.bold(component.name)}${retryNote}
|
|
5111
5302
|
${outputBuf}`);
|
|
5112
|
-
if (
|
|
5303
|
+
if (response.run.timedOut) {
|
|
5113
5304
|
return {
|
|
5114
5305
|
componentName: component.name,
|
|
5115
5306
|
classified: 0,
|
|
@@ -5121,18 +5312,19 @@ ${outputBuf}`);
|
|
|
5121
5312
|
renamedSlotsCount: renames.length
|
|
5122
5313
|
};
|
|
5123
5314
|
}
|
|
5124
|
-
if (
|
|
5125
|
-
lastError =
|
|
5126
|
-
continue;
|
|
5127
|
-
}
|
|
5128
|
-
const { calls, warnings } = parseToolCallLines(result.stdout);
|
|
5129
|
-
if (calls.length === 0) {
|
|
5130
|
-
lastError = describeAgentFailure(result);
|
|
5315
|
+
if (response.failure) {
|
|
5316
|
+
lastError = response.failure;
|
|
5131
5317
|
continue;
|
|
5132
5318
|
}
|
|
5133
|
-
const applied = applyToolCalls(
|
|
5134
|
-
|
|
5135
|
-
|
|
5319
|
+
const applied = applyToolCalls(
|
|
5320
|
+
db,
|
|
5321
|
+
sessionId2,
|
|
5322
|
+
component.component_id,
|
|
5323
|
+
component.name,
|
|
5324
|
+
response.calls,
|
|
5325
|
+
response.warnings,
|
|
5326
|
+
{ allowedComponentNames: allowedComponentNames2 }
|
|
5327
|
+
);
|
|
5136
5328
|
if (!noCache) {
|
|
5137
5329
|
const inputHash = hashComponentShape(cacheComponent);
|
|
5138
5330
|
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
@@ -5352,7 +5544,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5352
5544
|
sampleComponent.props.map((p) => p.type)
|
|
5353
5545
|
) : void 0;
|
|
5354
5546
|
const dryRunExistingComponentsInline = skill === "components" && existingContentfulEntities && sampleComponent ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, sampleComponent.name)) : void 0;
|
|
5355
|
-
const
|
|
5547
|
+
const promptOptions = {
|
|
5356
5548
|
skill,
|
|
5357
5549
|
mode: "autonomous",
|
|
5358
5550
|
rawComponentsInline: sampleInline ?? rawTokensInline,
|
|
@@ -5367,8 +5559,9 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5367
5559
|
existingComponentsInline: dryRunExistingComponentsInline,
|
|
5368
5560
|
existingTokensInline: skill === "components" ? existingTokensInline : void 0,
|
|
5369
5561
|
componentAllowlistInline: skill === "components" && allowedComponentNames2 ? JSON.stringify([...allowedComponentNames2].sort()) : void 0
|
|
5370
|
-
}
|
|
5371
|
-
|
|
5562
|
+
};
|
|
5563
|
+
const promptResponse = await createGenerateEndpoint({ invoker }).preview({ prompt: promptOptions });
|
|
5564
|
+
process.stdout.write(promptResponse.prompt + "\n");
|
|
5372
5565
|
await exitWithAnalytics(0);
|
|
5373
5566
|
}
|
|
5374
5567
|
const binary = resolveBinary(agent);
|
|
@@ -5538,21 +5731,20 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5538
5731
|
return;
|
|
5539
5732
|
}
|
|
5540
5733
|
}
|
|
5541
|
-
const
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
model,
|
|
5553
|
-
prompt,
|
|
5554
|
-
timeoutMs: DEFAULT_TIMEOUT_MS * 5
|
|
5734
|
+
const endpoint = createGenerateEndpoint({ invoker });
|
|
5735
|
+
const response = await endpoint.execute({
|
|
5736
|
+
prompt: {
|
|
5737
|
+
skill,
|
|
5738
|
+
mode: "autonomous",
|
|
5739
|
+
rawTokensInline,
|
|
5740
|
+
rawTokensFilename: opts.rawTokens ? resolve6(opts.rawTokens).split("/").pop() : void 0,
|
|
5741
|
+
tokensInline,
|
|
5742
|
+
tokenMapInline,
|
|
5743
|
+
outDir: process.cwd()
|
|
5744
|
+
},
|
|
5745
|
+
invocation: { agent, model, timeoutMs: DEFAULT_TIMEOUT_MS * 5 }
|
|
5555
5746
|
});
|
|
5747
|
+
const result = response.run;
|
|
5556
5748
|
if (result.timedOut) {
|
|
5557
5749
|
die(`Error: agent did not complete within ${DEFAULT_TIMEOUT_MS * 5 / 6e4} minutes`);
|
|
5558
5750
|
}
|
|
@@ -5560,7 +5752,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5560
5752
|
if (result.stderr) process.stderr.write(result.stderr);
|
|
5561
5753
|
die(`Error: agent exited with code ${result.exitCode}`);
|
|
5562
5754
|
}
|
|
5563
|
-
const { calls: tokenCalls, warnings: tokenWarnings } =
|
|
5755
|
+
const { calls: tokenCalls, warnings: tokenWarnings } = response;
|
|
5564
5756
|
const tokenCount = tokenCalls.filter((tc) => tc.tool === "set_token").length;
|
|
5565
5757
|
if (tokenCount === 0) {
|
|
5566
5758
|
process.stderr.write(
|
|
@@ -8984,7 +9176,7 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
8984
9176
|
);
|
|
8985
9177
|
}
|
|
8986
9178
|
}
|
|
8987
|
-
const
|
|
9179
|
+
const mapTokensPrompt = {
|
|
8988
9180
|
skill: "map-tokens",
|
|
8989
9181
|
mode: "autonomous",
|
|
8990
9182
|
generatedCdf,
|
|
@@ -8994,10 +9186,11 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
8994
9186
|
existingTokensInline,
|
|
8995
9187
|
...mapPromptText !== void 0 ? { skillContentOverride: mapPromptText } : {},
|
|
8996
9188
|
...mapPromptText === void 0 && mapPromptPath ? { skillPathOverride: mapPromptPath } : {}
|
|
8997
|
-
}
|
|
9189
|
+
};
|
|
8998
9190
|
if (opts.printPrompt) {
|
|
8999
|
-
const
|
|
9000
|
-
|
|
9191
|
+
const promptEndpoint = createGenerateEndpoint({ invoker: createLocalCliAgentInvoker() });
|
|
9192
|
+
const promptResponse = await promptEndpoint.preview({ prompt: mapTokensPrompt });
|
|
9193
|
+
process.stdout.write(promptResponse.prompt + "\n");
|
|
9001
9194
|
await exitWithAnalytics(0);
|
|
9002
9195
|
return;
|
|
9003
9196
|
}
|
|
@@ -9041,16 +9234,18 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
9041
9234
|
);
|
|
9042
9235
|
}
|
|
9043
9236
|
const stepId = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
|
|
9044
|
-
const prompt = await buildMapPrompt();
|
|
9045
9237
|
const invoker2 = createLocalCliAgentInvoker();
|
|
9046
|
-
const
|
|
9047
|
-
|
|
9048
|
-
|
|
9238
|
+
const endpoint = createGenerateEndpoint({ invoker: invoker2 });
|
|
9239
|
+
const response = await endpoint.execute({
|
|
9240
|
+
prompt: mapTokensPrompt,
|
|
9241
|
+
invocation: { agent, model, timeoutMs: DEFAULT_TIMEOUT_MS2 }
|
|
9242
|
+
});
|
|
9243
|
+
if (response.failure) {
|
|
9244
|
+
const error = response.run.timedOut ? `timed out after ${DEFAULT_TIMEOUT_MS2 / 6e4} minutes` : response.failure;
|
|
9049
9245
|
updateStep(db, stepId, "failed", {}, error);
|
|
9050
9246
|
die(`Error: map tokens agent failed \u2014 ${error}`);
|
|
9051
9247
|
}
|
|
9052
|
-
const {
|
|
9053
|
-
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, calls, parseWarnings);
|
|
9248
|
+
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, response.calls, response.warnings);
|
|
9054
9249
|
if (!noCache) {
|
|
9055
9250
|
storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId2, false, promptHash);
|
|
9056
9251
|
}
|
|
@@ -10225,7 +10420,7 @@ var init_use_terminal_size = __esm({
|
|
|
10225
10420
|
});
|
|
10226
10421
|
|
|
10227
10422
|
// packages/experience-design-system-cli/src/apply/tokens.ts
|
|
10228
|
-
var
|
|
10423
|
+
var init_tokens2 = __esm({
|
|
10229
10424
|
"packages/experience-design-system-cli/src/apply/tokens.ts"() {
|
|
10230
10425
|
"use strict";
|
|
10231
10426
|
init_command2();
|
|
@@ -10811,7 +11006,7 @@ var init_WizardPreviewStep = __esm({
|
|
|
10811
11006
|
init_theme();
|
|
10812
11007
|
init_useImmediateInput();
|
|
10813
11008
|
init_use_terminal_size();
|
|
10814
|
-
|
|
11009
|
+
init_tokens2();
|
|
10815
11010
|
init_preview_diff();
|
|
10816
11011
|
init_StepHeader();
|
|
10817
11012
|
init_SpaceEnvironment();
|
|
@@ -18744,9 +18939,9 @@ var init_wizard_generate_progress = __esm({
|
|
|
18744
18939
|
});
|
|
18745
18940
|
|
|
18746
18941
|
// packages/experience-design-system-cli/src/import/tui/spawn-generate.ts
|
|
18747
|
-
import { spawn as
|
|
18942
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
18748
18943
|
function spawnGenerateChild(opts) {
|
|
18749
|
-
const child =
|
|
18944
|
+
const child = spawn3(opts.command, opts.args);
|
|
18750
18945
|
let stdout = "";
|
|
18751
18946
|
let stderr = "";
|
|
18752
18947
|
child.stdout?.on("data", (d) => {
|
|
@@ -24285,7 +24480,7 @@ var init_runLivePreview = __esm({
|
|
|
24285
24480
|
"packages/experience-design-system-cli/src/import/tui/runLivePreview.ts"() {
|
|
24286
24481
|
"use strict";
|
|
24287
24482
|
init_api_client();
|
|
24288
|
-
|
|
24483
|
+
init_tokens2();
|
|
24289
24484
|
init_db();
|
|
24290
24485
|
TimeoutError = class extends Error {
|
|
24291
24486
|
constructor(message = "live-preview timed out") {
|
|
@@ -24691,7 +24886,7 @@ function useReviewFinalize({
|
|
|
24691
24886
|
var init_useReviewSession = __esm({
|
|
24692
24887
|
"packages/experience-design-system-cli/src/import/tui/hooks/useReviewSession.ts"() {
|
|
24693
24888
|
"use strict";
|
|
24694
|
-
|
|
24889
|
+
init_tokens2();
|
|
24695
24890
|
init_db();
|
|
24696
24891
|
init_history();
|
|
24697
24892
|
init_useFinalizePreview();
|
|
@@ -27059,7 +27254,7 @@ import { join as join20, resolve as resolve17 } from "node:path";
|
|
|
27059
27254
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27060
27255
|
import { access as access7, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
27061
27256
|
import { tmpdir } from "node:os";
|
|
27062
|
-
import { execFile as execFile2, spawn as
|
|
27257
|
+
import { execFile as execFile2, spawn as spawn4 } from "node:child_process";
|
|
27063
27258
|
import { mkdir as mkdir5 } from "node:fs/promises";
|
|
27064
27259
|
import { buildCDF as buildCDF3, validateCDF as validateCDF3, validateSlotReferences as validateSlotReferences2 } from "@contentful/experience-design-system-types";
|
|
27065
27260
|
import { jsx as jsx50, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
@@ -27121,7 +27316,7 @@ function runCli(args) {
|
|
|
27121
27316
|
}
|
|
27122
27317
|
function runSpawnedCli(args, onStderr, onStdout) {
|
|
27123
27318
|
return new Promise((res) => {
|
|
27124
|
-
const child =
|
|
27319
|
+
const child = spawn4("node", args);
|
|
27125
27320
|
let stdout = "";
|
|
27126
27321
|
let stderr = "";
|
|
27127
27322
|
child.stdout.on("data", (d) => {
|
|
@@ -29268,7 +29463,7 @@ var init_WizardApp = __esm({
|
|
|
29268
29463
|
init_wizard_422_helpers();
|
|
29269
29464
|
init_wizard_generate_progress();
|
|
29270
29465
|
init_spawn_generate();
|
|
29271
|
-
|
|
29466
|
+
init_tokens2();
|
|
29272
29467
|
init_preview_utils();
|
|
29273
29468
|
init_db();
|
|
29274
29469
|
init_ScopeGateStep();
|
|
@@ -29416,7 +29611,7 @@ var init_agent_definitions = __esm({
|
|
|
29416
29611
|
});
|
|
29417
29612
|
|
|
29418
29613
|
// packages/experience-design-system-cli/src/setup/lib/shell.ts
|
|
29419
|
-
import { execFile as execFile3, spawn as
|
|
29614
|
+
import { execFile as execFile3, spawn as spawn5 } from "node:child_process";
|
|
29420
29615
|
import { access as access8 } from "node:fs/promises";
|
|
29421
29616
|
import { promisify as promisify2 } from "node:util";
|
|
29422
29617
|
async function binaryExists(name) {
|
|
@@ -29432,7 +29627,7 @@ async function pathExists3(path) {
|
|
|
29432
29627
|
}
|
|
29433
29628
|
function runSpawn(cmd, args, opts = {}) {
|
|
29434
29629
|
return new Promise((resolve21) => {
|
|
29435
|
-
const child =
|
|
29630
|
+
const child = spawn5(cmd, args, {
|
|
29436
29631
|
cwd: opts.cwd,
|
|
29437
29632
|
env: opts.env ?? process.env,
|
|
29438
29633
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -31846,7 +32041,7 @@ __export(program_exports, {
|
|
|
31846
32041
|
resolveBedrockFromAncestors: () => resolveBedrockFromAncestors,
|
|
31847
32042
|
runBuild: () => runBuild
|
|
31848
32043
|
});
|
|
31849
|
-
import { spawn as
|
|
32044
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
31850
32045
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
31851
32046
|
import { dirname as dirname13, join as join26, resolve as resolve20 } from "node:path";
|
|
31852
32047
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
@@ -31888,7 +32083,7 @@ function registerBuildCommand(program) {
|
|
|
31888
32083
|
const pkgRoot = resolve20(dirname13(fileURLToPath4(import.meta.url)), "..", "..");
|
|
31889
32084
|
process.stderr.write("\u2699 Building from source...\n");
|
|
31890
32085
|
const { exitCode } = await runBuild({
|
|
31891
|
-
spawnFn: () =>
|
|
32086
|
+
spawnFn: () => spawn6("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|
|
31892
32087
|
stderrWrite: (s) => process.stderr.write(s)
|
|
31893
32088
|
});
|
|
31894
32089
|
process.exit(exitCode);
|