@contentful/experience-design-system-cli 2.34.5-dev-build-b70b5f29.0 → 2.34.5-dev-build-d8f04e9d.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 +497 -692
- package/dist/src/lib/agent-output.d.ts +0 -4
- package/package.json +6 -6
package/dist/src/index.js
CHANGED
|
@@ -160,253 +160,21 @@ var init_render_with_goodbye = __esm({
|
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
// packages/experience-design-system-generation/dist/src/
|
|
163
|
+
// packages/experience-design-system-generation/dist/src/agent-names.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/
|
|
168
|
+
var init_agent_names = __esm({
|
|
169
|
+
"packages/experience-design-system-generation/dist/src/agent-names.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/
|
|
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
|
|
176
|
+
// packages/experience-design-system-generation/dist/src/agent-runner.js
|
|
259
177
|
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
|
|
410
178
|
function findJsonObjectEnd(line) {
|
|
411
179
|
let depth = 0;
|
|
412
180
|
let inString = false;
|
|
@@ -642,229 +410,312 @@ function parseMapTokenPropToolCallLines(stdout) {
|
|
|
642
410
|
warnings.push(`map_token_prop '${rec.component}.${String(rec.prop)}': missing or empty token_allowed \u2014 skipped`);
|
|
643
411
|
continue;
|
|
644
412
|
}
|
|
645
|
-
|
|
413
|
+
const call = {
|
|
646
414
|
tool: "map_token_prop",
|
|
647
415
|
component: rec.component,
|
|
648
416
|
prop: rec.prop,
|
|
649
417
|
token_allowed: rec.token_allowed
|
|
650
|
-
}
|
|
418
|
+
};
|
|
419
|
+
calls.push(call);
|
|
651
420
|
}
|
|
652
421
|
return { calls, warnings };
|
|
653
422
|
}
|
|
654
|
-
function
|
|
655
|
-
const
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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();
|
|
423
|
+
function resolveBinary(agent) {
|
|
424
|
+
const envKey = `EDS_AGENT_BINARY_${agent.toUpperCase()}`;
|
|
425
|
+
const override = process.env[envKey];
|
|
426
|
+
if (override && override.trim())
|
|
427
|
+
return override.trim();
|
|
428
|
+
return AGENT_BINARIES[agent];
|
|
669
429
|
}
|
|
670
|
-
|
|
671
|
-
|
|
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
|
-
};
|
|
430
|
+
function agentSupportsBedrock(agent) {
|
|
431
|
+
return BEDROCK_CAPABLE_AGENTS.has(agent);
|
|
693
432
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
return
|
|
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.`;
|
|
433
|
+
function resolveAgentModel(agent, explicit, bedrock = false) {
|
|
434
|
+
if (explicit && explicit.trim())
|
|
435
|
+
return explicit.trim();
|
|
436
|
+
const override = process.env[`EDS_AGENT_MODEL_${agent.toUpperCase()}`];
|
|
437
|
+
if (override && override.trim())
|
|
438
|
+
return override.trim();
|
|
439
|
+
if (bedrock && agent === "codex")
|
|
440
|
+
return DEFAULT_CODEX_BEDROCK_MODEL;
|
|
441
|
+
if (bedrock && agent === "opencode")
|
|
442
|
+
return withBedrockProviderPrefix(DEFAULT_OPENCODE_MODEL);
|
|
443
|
+
return DEFAULT_MODELS[agent];
|
|
747
444
|
}
|
|
748
|
-
|
|
749
|
-
"
|
|
750
|
-
|
|
445
|
+
function withBedrockProviderPrefix(model) {
|
|
446
|
+
return model.includes("/") ? model : `amazon-bedrock/${model}`;
|
|
447
|
+
}
|
|
448
|
+
function codexBedrockConfigArgs() {
|
|
449
|
+
const region = process.env.AWS_REGION?.trim() || process.env.AWS_DEFAULT_REGION?.trim() || DEFAULT_CODEX_BEDROCK_REGION;
|
|
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
|
+
}
|
|
751
472
|
}
|
|
752
|
-
});
|
|
753
|
-
|
|
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.`;
|
|
779
473
|
}
|
|
780
|
-
|
|
781
|
-
|
|
474
|
+
async function runAgent(options) {
|
|
475
|
+
const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
|
|
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"() {
|
|
782
615
|
"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";
|
|
783
644
|
}
|
|
784
645
|
});
|
|
785
646
|
|
|
786
|
-
// packages/experience-design-system-generation/dist/src/
|
|
787
|
-
function
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
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.`;
|
|
647
|
+
// packages/experience-design-system-generation/dist/src/agent-invoker.js
|
|
648
|
+
function createLocalCliAgentInvoker(options = {}) {
|
|
649
|
+
const { onDebugEvent } = options;
|
|
650
|
+
return {
|
|
651
|
+
invoke(invokeOptions) {
|
|
652
|
+
return runAgent({ ...invokeOptions, onDebugEvent });
|
|
653
|
+
},
|
|
654
|
+
checkAuth(agent) {
|
|
655
|
+
return checkAgentAuth(agent);
|
|
656
|
+
}
|
|
657
|
+
};
|
|
812
658
|
}
|
|
813
|
-
var
|
|
814
|
-
"packages/experience-design-system-generation/dist/src/
|
|
659
|
+
var init_agent_invoker = __esm({
|
|
660
|
+
"packages/experience-design-system-generation/dist/src/agent-invoker.js"() {
|
|
815
661
|
"use strict";
|
|
662
|
+
init_agent_runner();
|
|
816
663
|
}
|
|
817
664
|
});
|
|
818
665
|
|
|
819
|
-
// packages/experience-design-system-generation/dist/src/
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
{
|
|
835
|
-
|
|
836
|
-
{"tool":"set_token","path":"<dot.notation.path>","type":"<DTCG type>","value":<value>,"description":"<reason>"}
|
|
837
|
-
\`\`\`
|
|
666
|
+
// packages/experience-design-system-generation/dist/src/prompt-builder.js
|
|
667
|
+
import { existsSync } from "node:fs";
|
|
668
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
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}
|
|
838
682
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
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.`;
|
|
683
|
+
Skill instructions follow:
|
|
684
|
+
---
|
|
685
|
+
${skillContent}`;
|
|
848
686
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
687
|
+
function resolveSkillPath(skill) {
|
|
688
|
+
if (!(skill in SKILL_FILES))
|
|
689
|
+
throw new Error(`Invalid skill: ${skill}`);
|
|
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;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async function readSkillFile(skill, override) {
|
|
704
|
+
if (override) {
|
|
705
|
+
const skillPath2 = resolve(override);
|
|
706
|
+
try {
|
|
707
|
+
return await readFile2(skillPath2, "utf8");
|
|
708
|
+
} catch {
|
|
709
|
+
throw new Error(`custom prompt file not found (skill: ${skill}, path: ${skillPath2})`);
|
|
710
|
+
}
|
|
852
711
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
"use strict";
|
|
859
|
-
init_components();
|
|
860
|
-
init_map_tokens();
|
|
861
|
-
init_select();
|
|
862
|
-
init_tokens();
|
|
712
|
+
const skillPath = resolveSkillPath(skill);
|
|
713
|
+
try {
|
|
714
|
+
return await readFile2(skillPath, "utf8");
|
|
715
|
+
} catch {
|
|
716
|
+
throw new Error(`skill file missing from CLI installation \u2014 try reinstalling the CLI (looked for: ${skillPath})`);
|
|
863
717
|
}
|
|
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";
|
|
718
|
+
}
|
|
868
719
|
function inferFenceLang(filename) {
|
|
869
720
|
if (!filename)
|
|
870
721
|
return "json";
|
|
@@ -924,7 +775,7 @@ function renderTokenCandidateSection(kind, entries) {
|
|
|
924
775
|
return `${label}, one leaf token per line as \`path \xB7 type\`, no \`$value\`:
|
|
925
776
|
${formatTokenCandidateLines(entries)}`;
|
|
926
777
|
}
|
|
927
|
-
function
|
|
778
|
+
function buildPreamble(options) {
|
|
928
779
|
const { skill, rawComponentsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs, existingComponentsInline, existingTokensInline, componentAllowlistInline } = options;
|
|
929
780
|
const sections = [];
|
|
930
781
|
if (existingComponentsInline) {
|
|
@@ -940,7 +791,7 @@ ${existingTokensInline}
|
|
|
940
791
|
\`\`\``);
|
|
941
792
|
}
|
|
942
793
|
if (componentAllowlistInline) {
|
|
943
|
-
sections.push(`Known component names for slot allowed_components (hard allowlist; never use any other name)
|
|
794
|
+
sections.push(`Known component names for slot allowed_components (hard allowlist; never use any other name):
|
|
944
795
|
\`\`\`json
|
|
945
796
|
${componentAllowlistInline}
|
|
946
797
|
\`\`\``);
|
|
@@ -1030,56 +881,149 @@ ${JSON.stringify(withoutContent.map((ref) => ({ component: ref.component, source
|
|
|
1030
881
|
\`\`\``);
|
|
1031
882
|
}
|
|
1032
883
|
}
|
|
1033
|
-
|
|
884
|
+
const inputBlock = sections.length > 0 ? `
|
|
1034
885
|
|
|
1035
886
|
${sections.join("\n\n")}` : "";
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
"packages/experience-design-system-generation/dist/src/generate/services/prompt-context-service.js"() {
|
|
1039
|
-
"use strict";
|
|
1040
|
-
}
|
|
1041
|
-
});
|
|
1042
|
-
|
|
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;
|
|
887
|
+
if (skill === "components") {
|
|
888
|
+
return buildComponentsAutonomousPreamble(inputBlock);
|
|
1062
889
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
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
|
-
}
|
|
890
|
+
if (skill === "select") {
|
|
891
|
+
return buildSelectAutonomousPreamble(inputBlock);
|
|
1072
892
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
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})`);
|
|
893
|
+
if (skill === "map-tokens") {
|
|
894
|
+
return buildMapTokensAutonomousPreamble(inputBlock);
|
|
1078
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
|
+
}
|
|
970
|
+
function buildMapTokensAutonomousPreamble(inputBlock) {
|
|
971
|
+
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.
|
|
972
|
+
|
|
973
|
+
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.
|
|
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
|
+
\`\`\`
|
|
986
|
+
|
|
987
|
+
Rules:
|
|
988
|
+
- Emit exactly one JSON object per line. No multi-line JSON. No markdown fences around the lines.
|
|
989
|
+
- Only emit a call for a prop that appears in the "Generated CDF so far" section.
|
|
990
|
+
- 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.
|
|
991
|
+
- \`token_allowed\` is required and must be non-empty when the call is emitted.
|
|
992
|
+
- 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.
|
|
993
|
+
- You may emit prose lines (not starting with \`{\`) anywhere \u2014 they are ignored by the parser and serve as your reasoning log.`;
|
|
994
|
+
}
|
|
995
|
+
function buildTokensAutonomousPreamble(inputBlock) {
|
|
996
|
+
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.
|
|
997
|
+
|
|
998
|
+
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.
|
|
999
|
+
|
|
1000
|
+
All input data is provided inline below \u2014 do not read any additional files.${inputBlock}
|
|
1001
|
+
|
|
1002
|
+
## Output protocol
|
|
1003
|
+
|
|
1004
|
+
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.
|
|
1005
|
+
|
|
1006
|
+
The two tool calls you may emit are:
|
|
1007
|
+
|
|
1008
|
+
\`\`\`
|
|
1009
|
+
{"tool":"set_group","path":"<dot.notation.path>","description":"<optional group description>"}
|
|
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.`;
|
|
1079
1023
|
}
|
|
1080
1024
|
var SKILL_FILES;
|
|
1081
|
-
var
|
|
1082
|
-
"packages/experience-design-system-generation/dist/src/
|
|
1025
|
+
var init_prompt_builder = __esm({
|
|
1026
|
+
"packages/experience-design-system-generation/dist/src/prompt-builder.js"() {
|
|
1083
1027
|
"use strict";
|
|
1084
1028
|
SKILL_FILES = {
|
|
1085
1029
|
components: "generate-components.md",
|
|
@@ -1090,131 +1034,13 @@ var init_skill_loader = __esm({
|
|
|
1090
1034
|
}
|
|
1091
1035
|
});
|
|
1092
1036
|
|
|
1093
|
-
// packages/experience-design-system-generation/dist/src/
|
|
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
|
|
1037
|
+
// packages/experience-design-system-generation/dist/src/progress.js
|
|
1134
1038
|
function formatGenerateProgressLine(done, total, name) {
|
|
1135
1039
|
return `progress=generate:${done}/${total}:${name}`;
|
|
1136
1040
|
}
|
|
1137
|
-
var
|
|
1138
|
-
"packages/experience-design-system-generation/dist/src/
|
|
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"() {
|
|
1041
|
+
var init_progress = __esm({
|
|
1042
|
+
"packages/experience-design-system-generation/dist/src/progress.js"() {
|
|
1147
1043
|
"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"]);
|
|
1218
1044
|
}
|
|
1219
1045
|
});
|
|
1220
1046
|
|
|
@@ -1223,12 +1049,10 @@ var src_exports = {};
|
|
|
1223
1049
|
__export(src_exports, {
|
|
1224
1050
|
AGENT_NAMES: () => AGENT_NAMES,
|
|
1225
1051
|
DEFAULT_AGENT_NAME: () => DEFAULT_AGENT_NAME,
|
|
1226
|
-
GenerateRequestError: () => GenerateRequestError,
|
|
1227
1052
|
agentSupportsBedrock: () => agentSupportsBedrock,
|
|
1228
1053
|
buildArgs: () => buildArgs,
|
|
1229
1054
|
buildPrompt: () => buildPrompt,
|
|
1230
1055
|
checkAgentAuth: () => checkAgentAuth,
|
|
1231
|
-
createGenerateEndpoint: () => createGenerateEndpoint,
|
|
1232
1056
|
createLocalCliAgentInvoker: () => createLocalCliAgentInvoker,
|
|
1233
1057
|
describeAgentFailure: () => describeAgentFailure,
|
|
1234
1058
|
extractSentinelOutput: () => extractSentinelOutput,
|
|
@@ -1247,18 +1071,11 @@ __export(src_exports, {
|
|
|
1247
1071
|
var init_src = __esm({
|
|
1248
1072
|
"packages/experience-design-system-generation/dist/src/index.js"() {
|
|
1249
1073
|
"use strict";
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
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();
|
|
1074
|
+
init_agent_names();
|
|
1075
|
+
init_agent_runner();
|
|
1076
|
+
init_agent_invoker();
|
|
1077
|
+
init_prompt_builder();
|
|
1078
|
+
init_progress();
|
|
1262
1079
|
}
|
|
1263
1080
|
});
|
|
1264
1081
|
|
|
@@ -1526,23 +1343,17 @@ var init_debug_logger = __esm({
|
|
|
1526
1343
|
});
|
|
1527
1344
|
|
|
1528
1345
|
// packages/experience-design-system-cli/src/lib/agent-output.ts
|
|
1529
|
-
function
|
|
1346
|
+
async function invokeAgentWithOutput(invoker2, options, verbose) {
|
|
1530
1347
|
let output = "";
|
|
1531
1348
|
const formatter = new OutputFormatter(verbose, (chunk) => {
|
|
1532
1349
|
output += chunk;
|
|
1533
1350
|
});
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
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() };
|
|
1351
|
+
const result = await invoker2.invoke({
|
|
1352
|
+
...options,
|
|
1353
|
+
onOutput: (chunk) => formatter.push(chunk)
|
|
1354
|
+
});
|
|
1355
|
+
formatter.flush();
|
|
1356
|
+
return { result, output };
|
|
1546
1357
|
}
|
|
1547
1358
|
var init_agent_output = __esm({
|
|
1548
1359
|
"packages/experience-design-system-cli/src/lib/agent-output.ts"() {
|
|
@@ -5271,7 +5082,7 @@ async function runOneComponent(options, component, index, total) {
|
|
|
5271
5082
|
component.props.map((p) => p.type)
|
|
5272
5083
|
);
|
|
5273
5084
|
const existingComponentsInline = existingContentfulEntities ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, component.name)) : void 0;
|
|
5274
|
-
const
|
|
5085
|
+
const prompt = await buildPrompt({
|
|
5275
5086
|
skill: "components",
|
|
5276
5087
|
mode: "autonomous",
|
|
5277
5088
|
rawComponentsInline,
|
|
@@ -5285,22 +5096,20 @@ async function runOneComponent(options, component, index, total) {
|
|
|
5285
5096
|
existingComponentsInline,
|
|
5286
5097
|
existingTokensInline,
|
|
5287
5098
|
componentAllowlistInline: JSON.stringify([...allowedComponentNames2].sort())
|
|
5288
|
-
};
|
|
5289
|
-
const endpoint = createGenerateEndpoint({ invoker });
|
|
5099
|
+
});
|
|
5290
5100
|
const maxAttempts = 2;
|
|
5291
5101
|
let lastError = "";
|
|
5292
5102
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
5293
5103
|
if (attempt > 1) await new Promise((res) => setTimeout(res, RETRY_BACKOFF_MS));
|
|
5294
|
-
const
|
|
5295
|
-
|
|
5296
|
-
prompt:
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
const outputBuf = outputCapture.finish();
|
|
5104
|
+
const { result, output: outputBuf } = await invokeAgentWithOutput(
|
|
5105
|
+
invoker,
|
|
5106
|
+
{ agent, model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS },
|
|
5107
|
+
verbose
|
|
5108
|
+
);
|
|
5300
5109
|
const retryNote = attempt > 1 ? ` ${c.yellow(`retrying (${attempt}/${maxAttempts})`)}` : "";
|
|
5301
5110
|
process.stderr.write(` ${pos} ${c.bold(component.name)}${retryNote}
|
|
5302
5111
|
${outputBuf}`);
|
|
5303
|
-
if (
|
|
5112
|
+
if (result.timedOut) {
|
|
5304
5113
|
return {
|
|
5305
5114
|
componentName: component.name,
|
|
5306
5115
|
classified: 0,
|
|
@@ -5312,19 +5121,18 @@ ${outputBuf}`);
|
|
|
5312
5121
|
renamedSlotsCount: renames.length
|
|
5313
5122
|
};
|
|
5314
5123
|
}
|
|
5315
|
-
if (
|
|
5316
|
-
lastError =
|
|
5124
|
+
if (result.exitCode !== 0) {
|
|
5125
|
+
lastError = describeAgentFailure(result);
|
|
5126
|
+
continue;
|
|
5127
|
+
}
|
|
5128
|
+
const { calls, warnings } = parseToolCallLines(result.stdout);
|
|
5129
|
+
if (calls.length === 0) {
|
|
5130
|
+
lastError = describeAgentFailure(result);
|
|
5317
5131
|
continue;
|
|
5318
5132
|
}
|
|
5319
|
-
const applied = applyToolCalls(
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
component.component_id,
|
|
5323
|
-
component.name,
|
|
5324
|
-
response.calls,
|
|
5325
|
-
response.warnings,
|
|
5326
|
-
{ allowedComponentNames: allowedComponentNames2 }
|
|
5327
|
-
);
|
|
5133
|
+
const applied = applyToolCalls(db, sessionId2, component.component_id, component.name, calls, warnings, {
|
|
5134
|
+
allowedComponentNames: allowedComponentNames2
|
|
5135
|
+
});
|
|
5328
5136
|
if (!noCache) {
|
|
5329
5137
|
const inputHash = hashComponentShape(cacheComponent);
|
|
5330
5138
|
storeCache(db, inputHash, "component", component.component_id, sessionId2, false, promptHash);
|
|
@@ -5544,7 +5352,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5544
5352
|
sampleComponent.props.map((p) => p.type)
|
|
5545
5353
|
) : void 0;
|
|
5546
5354
|
const dryRunExistingComponentsInline = skill === "components" && existingContentfulEntities && sampleComponent ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, sampleComponent.name)) : void 0;
|
|
5547
|
-
const
|
|
5355
|
+
const prompt = await buildPrompt({
|
|
5548
5356
|
skill,
|
|
5549
5357
|
mode: "autonomous",
|
|
5550
5358
|
rawComponentsInline: sampleInline ?? rawTokensInline,
|
|
@@ -5559,9 +5367,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5559
5367
|
existingComponentsInline: dryRunExistingComponentsInline,
|
|
5560
5368
|
existingTokensInline: skill === "components" ? existingTokensInline : void 0,
|
|
5561
5369
|
componentAllowlistInline: skill === "components" && allowedComponentNames2 ? JSON.stringify([...allowedComponentNames2].sort()) : void 0
|
|
5562
|
-
};
|
|
5563
|
-
|
|
5564
|
-
process.stdout.write(promptResponse.prompt + "\n");
|
|
5370
|
+
});
|
|
5371
|
+
process.stdout.write(prompt + "\n");
|
|
5565
5372
|
await exitWithAnalytics(0);
|
|
5566
5373
|
}
|
|
5567
5374
|
const binary = resolveBinary(agent);
|
|
@@ -5731,20 +5538,21 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5731
5538
|
return;
|
|
5732
5539
|
}
|
|
5733
5540
|
}
|
|
5734
|
-
const
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5541
|
+
const prompt = await buildPrompt({
|
|
5542
|
+
skill,
|
|
5543
|
+
mode: "autonomous",
|
|
5544
|
+
rawTokensInline,
|
|
5545
|
+
rawTokensFilename: opts.rawTokens ? resolve6(opts.rawTokens).split("/").pop() : void 0,
|
|
5546
|
+
tokensInline,
|
|
5547
|
+
tokenMapInline,
|
|
5548
|
+
outDir: process.cwd()
|
|
5549
|
+
});
|
|
5550
|
+
const result = await invoker.invoke({
|
|
5551
|
+
agent,
|
|
5552
|
+
model,
|
|
5553
|
+
prompt,
|
|
5554
|
+
timeoutMs: DEFAULT_TIMEOUT_MS * 5
|
|
5746
5555
|
});
|
|
5747
|
-
const result = response.run;
|
|
5748
5556
|
if (result.timedOut) {
|
|
5749
5557
|
die(`Error: agent did not complete within ${DEFAULT_TIMEOUT_MS * 5 / 6e4} minutes`);
|
|
5750
5558
|
}
|
|
@@ -5752,7 +5560,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
5752
5560
|
if (result.stderr) process.stderr.write(result.stderr);
|
|
5753
5561
|
die(`Error: agent exited with code ${result.exitCode}`);
|
|
5754
5562
|
}
|
|
5755
|
-
const { calls: tokenCalls, warnings: tokenWarnings } =
|
|
5563
|
+
const { calls: tokenCalls, warnings: tokenWarnings } = parseTokenToolCallLines(result.stdout);
|
|
5756
5564
|
const tokenCount = tokenCalls.filter((tc) => tc.tool === "set_token").length;
|
|
5757
5565
|
if (tokenCount === 0) {
|
|
5758
5566
|
process.stderr.write(
|
|
@@ -9176,7 +8984,7 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
9176
8984
|
);
|
|
9177
8985
|
}
|
|
9178
8986
|
}
|
|
9179
|
-
const
|
|
8987
|
+
const buildMapPrompt = () => buildPrompt({
|
|
9180
8988
|
skill: "map-tokens",
|
|
9181
8989
|
mode: "autonomous",
|
|
9182
8990
|
generatedCdf,
|
|
@@ -9186,11 +8994,10 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
9186
8994
|
existingTokensInline,
|
|
9187
8995
|
...mapPromptText !== void 0 ? { skillContentOverride: mapPromptText } : {},
|
|
9188
8996
|
...mapPromptText === void 0 && mapPromptPath ? { skillPathOverride: mapPromptPath } : {}
|
|
9189
|
-
};
|
|
8997
|
+
});
|
|
9190
8998
|
if (opts.printPrompt) {
|
|
9191
|
-
const
|
|
9192
|
-
|
|
9193
|
-
process.stdout.write(promptResponse.prompt + "\n");
|
|
8999
|
+
const prompt2 = await buildMapPrompt();
|
|
9000
|
+
process.stdout.write(prompt2 + "\n");
|
|
9194
9001
|
await exitWithAnalytics(0);
|
|
9195
9002
|
return;
|
|
9196
9003
|
}
|
|
@@ -9234,18 +9041,16 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
9234
9041
|
);
|
|
9235
9042
|
}
|
|
9236
9043
|
const stepId = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
|
|
9044
|
+
const prompt = await buildMapPrompt();
|
|
9237
9045
|
const invoker2 = createLocalCliAgentInvoker();
|
|
9238
|
-
const
|
|
9239
|
-
|
|
9240
|
-
|
|
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;
|
|
9046
|
+
const result = await invoker2.invoke({ agent, model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS2 });
|
|
9047
|
+
if (result.timedOut || result.exitCode !== 0) {
|
|
9048
|
+
const error = result.timedOut ? `timed out after ${DEFAULT_TIMEOUT_MS2 / 6e4} minutes` : describeAgentFailure(result);
|
|
9245
9049
|
updateStep(db, stepId, "failed", {}, error);
|
|
9246
9050
|
die(`Error: map tokens agent failed \u2014 ${error}`);
|
|
9247
9051
|
}
|
|
9248
|
-
const {
|
|
9052
|
+
const { calls, warnings: parseWarnings } = parseMapTokenPropToolCallLines(result.stdout);
|
|
9053
|
+
const { applied, warnings } = applyMapTokenPropCalls(db, sessionId2, calls, parseWarnings);
|
|
9249
9054
|
if (!noCache) {
|
|
9250
9055
|
storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId2, false, promptHash);
|
|
9251
9056
|
}
|
|
@@ -10420,7 +10225,7 @@ var init_use_terminal_size = __esm({
|
|
|
10420
10225
|
});
|
|
10421
10226
|
|
|
10422
10227
|
// packages/experience-design-system-cli/src/apply/tokens.ts
|
|
10423
|
-
var
|
|
10228
|
+
var init_tokens = __esm({
|
|
10424
10229
|
"packages/experience-design-system-cli/src/apply/tokens.ts"() {
|
|
10425
10230
|
"use strict";
|
|
10426
10231
|
init_command2();
|
|
@@ -11006,7 +10811,7 @@ var init_WizardPreviewStep = __esm({
|
|
|
11006
10811
|
init_theme();
|
|
11007
10812
|
init_useImmediateInput();
|
|
11008
10813
|
init_use_terminal_size();
|
|
11009
|
-
|
|
10814
|
+
init_tokens();
|
|
11010
10815
|
init_preview_diff();
|
|
11011
10816
|
init_StepHeader();
|
|
11012
10817
|
init_SpaceEnvironment();
|
|
@@ -18939,9 +18744,9 @@ var init_wizard_generate_progress = __esm({
|
|
|
18939
18744
|
});
|
|
18940
18745
|
|
|
18941
18746
|
// packages/experience-design-system-cli/src/import/tui/spawn-generate.ts
|
|
18942
|
-
import { spawn as
|
|
18747
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
18943
18748
|
function spawnGenerateChild(opts) {
|
|
18944
|
-
const child =
|
|
18749
|
+
const child = spawn2(opts.command, opts.args);
|
|
18945
18750
|
let stdout = "";
|
|
18946
18751
|
let stderr = "";
|
|
18947
18752
|
child.stdout?.on("data", (d) => {
|
|
@@ -24480,7 +24285,7 @@ var init_runLivePreview = __esm({
|
|
|
24480
24285
|
"packages/experience-design-system-cli/src/import/tui/runLivePreview.ts"() {
|
|
24481
24286
|
"use strict";
|
|
24482
24287
|
init_api_client();
|
|
24483
|
-
|
|
24288
|
+
init_tokens();
|
|
24484
24289
|
init_db();
|
|
24485
24290
|
TimeoutError = class extends Error {
|
|
24486
24291
|
constructor(message = "live-preview timed out") {
|
|
@@ -24886,7 +24691,7 @@ function useReviewFinalize({
|
|
|
24886
24691
|
var init_useReviewSession = __esm({
|
|
24887
24692
|
"packages/experience-design-system-cli/src/import/tui/hooks/useReviewSession.ts"() {
|
|
24888
24693
|
"use strict";
|
|
24889
|
-
|
|
24694
|
+
init_tokens();
|
|
24890
24695
|
init_db();
|
|
24891
24696
|
init_history();
|
|
24892
24697
|
init_useFinalizePreview();
|
|
@@ -27254,7 +27059,7 @@ import { join as join20, resolve as resolve17 } from "node:path";
|
|
|
27254
27059
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27255
27060
|
import { access as access7, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
27256
27061
|
import { tmpdir } from "node:os";
|
|
27257
|
-
import { execFile as execFile2, spawn as
|
|
27062
|
+
import { execFile as execFile2, spawn as spawn3 } from "node:child_process";
|
|
27258
27063
|
import { mkdir as mkdir5 } from "node:fs/promises";
|
|
27259
27064
|
import { buildCDF as buildCDF3, validateCDF as validateCDF3, validateSlotReferences as validateSlotReferences2 } from "@contentful/experience-design-system-types";
|
|
27260
27065
|
import { jsx as jsx50, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
@@ -27316,7 +27121,7 @@ function runCli(args) {
|
|
|
27316
27121
|
}
|
|
27317
27122
|
function runSpawnedCli(args, onStderr, onStdout) {
|
|
27318
27123
|
return new Promise((res) => {
|
|
27319
|
-
const child =
|
|
27124
|
+
const child = spawn3("node", args);
|
|
27320
27125
|
let stdout = "";
|
|
27321
27126
|
let stderr = "";
|
|
27322
27127
|
child.stdout.on("data", (d) => {
|
|
@@ -29463,7 +29268,7 @@ var init_WizardApp = __esm({
|
|
|
29463
29268
|
init_wizard_422_helpers();
|
|
29464
29269
|
init_wizard_generate_progress();
|
|
29465
29270
|
init_spawn_generate();
|
|
29466
|
-
|
|
29271
|
+
init_tokens();
|
|
29467
29272
|
init_preview_utils();
|
|
29468
29273
|
init_db();
|
|
29469
29274
|
init_ScopeGateStep();
|
|
@@ -29611,7 +29416,7 @@ var init_agent_definitions = __esm({
|
|
|
29611
29416
|
});
|
|
29612
29417
|
|
|
29613
29418
|
// packages/experience-design-system-cli/src/setup/lib/shell.ts
|
|
29614
|
-
import { execFile as execFile3, spawn as
|
|
29419
|
+
import { execFile as execFile3, spawn as spawn4 } from "node:child_process";
|
|
29615
29420
|
import { access as access8 } from "node:fs/promises";
|
|
29616
29421
|
import { promisify as promisify2 } from "node:util";
|
|
29617
29422
|
async function binaryExists(name) {
|
|
@@ -29627,7 +29432,7 @@ async function pathExists3(path) {
|
|
|
29627
29432
|
}
|
|
29628
29433
|
function runSpawn(cmd, args, opts = {}) {
|
|
29629
29434
|
return new Promise((resolve21) => {
|
|
29630
|
-
const child =
|
|
29435
|
+
const child = spawn4(cmd, args, {
|
|
29631
29436
|
cwd: opts.cwd,
|
|
29632
29437
|
env: opts.env ?? process.env,
|
|
29633
29438
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -32041,7 +31846,7 @@ __export(program_exports, {
|
|
|
32041
31846
|
resolveBedrockFromAncestors: () => resolveBedrockFromAncestors,
|
|
32042
31847
|
runBuild: () => runBuild
|
|
32043
31848
|
});
|
|
32044
|
-
import { spawn as
|
|
31849
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
32045
31850
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
32046
31851
|
import { dirname as dirname13, join as join26, resolve as resolve20 } from "node:path";
|
|
32047
31852
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
@@ -32083,7 +31888,7 @@ function registerBuildCommand(program) {
|
|
|
32083
31888
|
const pkgRoot = resolve20(dirname13(fileURLToPath4(import.meta.url)), "..", "..");
|
|
32084
31889
|
process.stderr.write("\u2699 Building from source...\n");
|
|
32085
31890
|
const { exitCode } = await runBuild({
|
|
32086
|
-
spawnFn: () =>
|
|
31891
|
+
spawnFn: () => spawn5("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|
|
32087
31892
|
stderrWrite: (s) => process.stderr.write(s)
|
|
32088
31893
|
});
|
|
32089
31894
|
process.exit(exitCode);
|