@contentful/experience-design-system-generation 2.35.1-dev-build-35ec3f8d.0 → 2.35.1-dev-build-9605c7ee.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-generation",
3
- "version": "2.35.1-dev-build-35ec3f8d.0",
3
+ "version": "2.35.1-dev-build-9605c7ee.0",
4
4
  "description": "Agent-invocation and skill-prompt engine for the Contentful Experience Design System SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,4 +1,4 @@
1
1
  import type { PromptOptions, Skill } from '../../types/prompt.js';
2
- export declare function resolveSkillPath(skill: Skill): string;
3
- export declare function formatCustomPromptBanner(skill: 'components' | 'select', path: string): string;
2
+ export { resolveSkillPath, formatCustomPromptBanner } from './helpers/resolve-skill-file.js';
3
+ export type { Skill };
4
4
  export declare function buildPrompt(options: PromptOptions): Promise<string>;
@@ -1,126 +1,6 @@
1
- import { existsSync } from 'node:fs';
2
- import { readFile } from 'node:fs/promises';
3
- import { dirname, join, resolve } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { inferFenceLang, filterDesignTokenProps, buildTokenCandidateSections, } from './helpers/format-token-candidates.js';
6
- import { buildComponentsAutonomousPreamble, buildSelectAutonomousPreamble, buildMapTokensAutonomousPreamble, buildTokensAutonomousPreamble, } from './helpers/build-skill-preambles.js';
7
- const SKILL_FILES = {
8
- components: 'generate-components.md',
9
- tokens: 'generate-tokens.md',
10
- select: 'select-components.md',
11
- 'map-tokens': 'map-tokens.md',
12
- };
13
- export function resolveSkillPath(skill) {
14
- if (!(skill in SKILL_FILES))
15
- throw new Error(`Invalid skill: ${skill}`);
16
- const thisDir = dirname(fileURLToPath(import.meta.url));
17
- let dir = thisDir;
18
- for (;;) {
19
- const candidate = join(dir, 'skills');
20
- if (existsSync(candidate))
21
- return join(candidate, SKILL_FILES[skill]);
22
- const parent = resolve(dir, '..');
23
- if (parent === dir) {
24
- throw new Error(`skill file missing from CLI installation (could not locate skills/ directory from: ${thisDir})`);
25
- }
26
- dir = parent;
27
- }
28
- }
29
- export function formatCustomPromptBanner(skill, path) {
30
- return (`WARNING: Custom prompt active for ${skill}: ${path}\n` +
31
- ` Bundled invariants (utility-wrapper rejection, description content rules) do NOT apply.\n` +
32
- ` You are responsible for the prompt's correctness.\n`);
33
- }
34
- async function readSkillFile(skill, override) {
35
- if (override) {
36
- const skillPath = resolve(override);
37
- try {
38
- return await readFile(skillPath, 'utf8');
39
- }
40
- catch {
41
- throw new Error(`custom prompt file not found (skill: ${skill}, path: ${skillPath})`);
42
- }
43
- }
44
- const skillPath = resolveSkillPath(skill);
45
- try {
46
- return await readFile(skillPath, 'utf8');
47
- }
48
- catch {
49
- throw new Error(`skill file missing from CLI installation — try reinstalling the CLI (looked for: ${skillPath})`);
50
- }
51
- }
52
- function buildPreamble(options) {
53
- const { skill, rawComponentsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs, existingComponentsInline, existingTokensInline, componentAllowlistInline, } = options;
54
- const sections = [];
55
- if (existingComponentsInline) {
56
- sections.push(`Existing components in the target Contentful space (JSON) — use for alignment, not as a hard filter:\n\`\`\`json\n${existingComponentsInline}\n\`\`\``);
57
- }
58
- if (existingTokensInline) {
59
- sections.push(`Existing design tokens in the target Contentful space (JSON) — prefer binding to these paths over inventing new ones:\n\`\`\`json\n${existingTokensInline}\n\`\`\``);
60
- }
61
- if (componentAllowlistInline) {
62
- sections.push(`Known component names for slot allowed_components (hard allowlist; never use any other name):\n\`\`\`json\n${componentAllowlistInline}\n\`\`\``);
63
- }
64
- if (rawComponentsInline) {
65
- sections.push(`Raw component data (JSON):\n\`\`\`json\n${rawComponentsInline}\n\`\`\``);
66
- }
67
- if (rawTokensInline) {
68
- const lang = inferFenceLang(rawTokensFilename);
69
- const label = rawTokensFilename ? `Raw token source (${rawTokensFilename})` : 'Raw token source';
70
- sections.push(`${label}:\n\`\`\`${lang}\n${rawTokensInline}\n\`\`\``);
71
- }
72
- if (tokensInline) {
73
- sections.push(`DTCG token data (for token kind lookups):\n\`\`\`json\n${tokensInline}\n\`\`\``);
74
- }
75
- if (tokenMapInline) {
76
- sections.push(`Token-name sidecar (raw name → DTCG path):\n\`\`\`json\n${tokenMapInline}\n\`\`\``);
77
- }
78
- const filteredTokenProps = generatedCdf ? filterDesignTokenProps(generatedCdf) : undefined;
79
- if (filteredTokenProps && Object.keys(filteredTokenProps.filtered).length > 0) {
80
- sections.push(`Generated CDF so far — design-category token props only (JSON):\n\`\`\`json\n${JSON.stringify(filteredTokenProps.filtered)}\n\`\`\``);
81
- }
82
- if (tokenTree) {
83
- for (const section of buildTokenCandidateSections(tokenTree, filteredTokenProps)) {
84
- sections.push(section);
85
- }
86
- }
87
- if (componentSourceRefs && componentSourceRefs.length > 0) {
88
- const withContent = componentSourceRefs.filter((ref) => ref.content != null);
89
- const withoutContent = componentSourceRefs.filter((ref) => ref.content == null);
90
- if (withContent.length > 0) {
91
- const blocks = withContent.map((ref) => {
92
- const mainBlock = `#### ${ref.component} (\`${ref.sourcePath}\`)\n\`\`\`${inferFenceLang(ref.sourcePath)}\n${ref.content}\n\`\`\``;
93
- const siblingBlocks = (ref.siblingFiles ?? []).map((sibling) => `##### ${ref.component} — imported file \`${sibling.path}\`\n\`\`\`${inferFenceLang(sibling.path)}\n${sibling.content}\n\`\`\``);
94
- const truncationNote = ref.truncatedSiblingCount && ref.truncatedSiblingCount > 0
95
- ? [
96
- `##### ${ref.component} — +${ref.truncatedSiblingCount} more imported file${ref.truncatedSiblingCount === 1 ? '' : 's'} not shown (evidence may be incomplete)`,
97
- ]
98
- : [];
99
- const notShownNote = ref.usesNotShown && ref.usesNotShown.length > 0
100
- ? [
101
- `##### ${ref.component} — uses not shown: ${ref.usesNotShown.join(', ')}\n\nThe files above are excerpts, and each of these properties has at least one use that fell outside the excerpt budget. Treat their consumption as unknown, not absent: do not classify them \`token\` on what is shown, and do not conclude they are unread.`,
102
- ]
103
- : [];
104
- return [mainBlock, ...siblingBlocks, ...truncationNote, ...notShownNote].join('\n\n');
105
- });
106
- sections.push(`### Component source references\n\n${blocks.join('\n\n')}`);
107
- }
108
- if (withoutContent.length > 0) {
109
- const guidance = skill === 'components'
110
- ? 'there is no consumption evidence for these, so `token` cannot be earned for any of their props — classify from the prop signature alone, and any prop that would otherwise be enum-versus-token is `enum` (or `string`)'
111
- : 'there is no source evidence to narrow from — emit nothing for their props';
112
- sections.push(`Component source unavailable for (JSON) — ${guidance}:\n\`\`\`json\n${JSON.stringify(withoutContent.map((ref) => ({ component: ref.component, sourcePath: ref.sourcePath })))}\n\`\`\``);
113
- }
114
- }
115
- const inputBlock = sections.length > 0 ? `\n\n${sections.join('\n\n')}` : '';
116
- if (skill === 'components')
117
- return buildComponentsAutonomousPreamble(inputBlock);
118
- if (skill === 'select')
119
- return buildSelectAutonomousPreamble(inputBlock);
120
- if (skill === 'map-tokens')
121
- return buildMapTokensAutonomousPreamble(inputBlock);
122
- return buildTokensAutonomousPreamble(inputBlock);
123
- }
1
+ import { readSkillFile } from './helpers/resolve-skill-file.js';
2
+ import { buildPreamble } from './helpers/build-preamble.js';
3
+ export { resolveSkillPath, formatCustomPromptBanner } from './helpers/resolve-skill-file.js';
124
4
  export async function buildPrompt(options) {
125
5
  const skillContent = options.skillContentOverride ?? (await readSkillFile(options.skill, options.skillPathOverride));
126
6
  const preamble = buildPreamble(options);
@@ -0,0 +1,2 @@
1
+ import type { PromptOptions } from '../../../types/prompt.js';
2
+ export declare function buildPreamble(options: PromptOptions): string;
@@ -0,0 +1,48 @@
1
+ import { inferFenceLang, filterDesignTokenProps, buildTokenCandidateSections } from './format-token-candidates.js';
2
+ import { formatSourceRefsSection } from './format-source-refs.js';
3
+ import { buildComponentsAutonomousPreamble, buildSelectAutonomousPreamble, buildMapTokensAutonomousPreamble, buildTokensAutonomousPreamble, } from './build-skill-preambles.js';
4
+ export function buildPreamble(options) {
5
+ const { skill, rawComponentsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs, existingComponentsInline, existingTokensInline, componentAllowlistInline, } = options;
6
+ const sections = [];
7
+ if (existingComponentsInline) {
8
+ sections.push(`Existing components in the target Contentful space (JSON) — use for alignment, not as a hard filter:\n\`\`\`json\n${existingComponentsInline}\n\`\`\``);
9
+ }
10
+ if (existingTokensInline) {
11
+ sections.push(`Existing design tokens in the target Contentful space (JSON) — prefer binding to these paths over inventing new ones:\n\`\`\`json\n${existingTokensInline}\n\`\`\``);
12
+ }
13
+ if (componentAllowlistInline) {
14
+ sections.push(`Known component names for slot allowed_components (hard allowlist; never use any other name):\n\`\`\`json\n${componentAllowlistInline}\n\`\`\``);
15
+ }
16
+ if (rawComponentsInline) {
17
+ sections.push(`Raw component data (JSON):\n\`\`\`json\n${rawComponentsInline}\n\`\`\``);
18
+ }
19
+ if (rawTokensInline) {
20
+ const lang = inferFenceLang(rawTokensFilename);
21
+ const label = rawTokensFilename ? `Raw token source (${rawTokensFilename})` : 'Raw token source';
22
+ sections.push(`${label}:\n\`\`\`${lang}\n${rawTokensInline}\n\`\`\``);
23
+ }
24
+ if (tokensInline) {
25
+ sections.push(`DTCG token data (for token kind lookups):\n\`\`\`json\n${tokensInline}\n\`\`\``);
26
+ }
27
+ if (tokenMapInline) {
28
+ sections.push(`Token-name sidecar (raw name → DTCG path):\n\`\`\`json\n${tokenMapInline}\n\`\`\``);
29
+ }
30
+ const filteredTokenProps = generatedCdf ? filterDesignTokenProps(generatedCdf) : undefined;
31
+ if (filteredTokenProps && Object.keys(filteredTokenProps.filtered).length > 0) {
32
+ sections.push(`Generated CDF so far — design-category token props only (JSON):\n\`\`\`json\n${JSON.stringify(filteredTokenProps.filtered)}\n\`\`\``);
33
+ }
34
+ if (tokenTree) {
35
+ sections.push(...buildTokenCandidateSections(tokenTree, filteredTokenProps));
36
+ }
37
+ if (componentSourceRefs && componentSourceRefs.length > 0) {
38
+ sections.push(...formatSourceRefsSection(componentSourceRefs, skill));
39
+ }
40
+ const inputBlock = sections.length > 0 ? `\n\n${sections.join('\n\n')}` : '';
41
+ if (skill === 'components')
42
+ return buildComponentsAutonomousPreamble(inputBlock);
43
+ if (skill === 'select')
44
+ return buildSelectAutonomousPreamble(inputBlock);
45
+ if (skill === 'map-tokens')
46
+ return buildMapTokensAutonomousPreamble(inputBlock);
47
+ return buildTokensAutonomousPreamble(inputBlock);
48
+ }
@@ -0,0 +1,2 @@
1
+ import type { ComponentSourceRef, Skill } from '../../../types/prompt.js';
2
+ export declare function formatSourceRefsSection(refs: ComponentSourceRef[], skill: Skill): string[];
@@ -0,0 +1,31 @@
1
+ import { inferFenceLang } from './format-token-candidates.js';
2
+ function formatSourceRefBlock(ref) {
3
+ const mainBlock = `#### ${ref.component} (\`${ref.sourcePath}\`)\n\`\`\`${inferFenceLang(ref.sourcePath)}\n${ref.content}\n\`\`\``;
4
+ const siblingBlocks = (ref.siblingFiles ?? []).map((sibling) => `##### ${ref.component} — imported file \`${sibling.path}\`\n\`\`\`${inferFenceLang(sibling.path)}\n${sibling.content}\n\`\`\``);
5
+ const truncationNote = ref.truncatedSiblingCount && ref.truncatedSiblingCount > 0
6
+ ? [
7
+ `##### ${ref.component} — +${ref.truncatedSiblingCount} more imported file${ref.truncatedSiblingCount === 1 ? '' : 's'} not shown (evidence may be incomplete)`,
8
+ ]
9
+ : [];
10
+ const notShownNote = ref.usesNotShown && ref.usesNotShown.length > 0
11
+ ? [
12
+ `##### ${ref.component} — uses not shown: ${ref.usesNotShown.join(', ')}\n\nThe files above are excerpts, and each of these properties has at least one use that fell outside the excerpt budget. Treat their consumption as unknown, not absent: do not classify them \`token\` on what is shown, and do not conclude they are unread.`,
13
+ ]
14
+ : [];
15
+ return [mainBlock, ...siblingBlocks, ...truncationNote, ...notShownNote].join('\n\n');
16
+ }
17
+ export function formatSourceRefsSection(refs, skill) {
18
+ const sections = [];
19
+ const withContent = refs.filter((ref) => ref.content != null);
20
+ const withoutContent = refs.filter((ref) => ref.content == null);
21
+ if (withContent.length > 0) {
22
+ sections.push(`### Component source references\n\n${withContent.map(formatSourceRefBlock).join('\n\n')}`);
23
+ }
24
+ if (withoutContent.length > 0) {
25
+ const guidance = skill === 'components'
26
+ ? 'there is no consumption evidence for these, so `token` cannot be earned for any of their props — classify from the prop signature alone, and any prop that would otherwise be enum-versus-token is `enum` (or `string`)'
27
+ : 'there is no source evidence to narrow from — emit nothing for their props';
28
+ sections.push(`Component source unavailable for (JSON) — ${guidance}:\n\`\`\`json\n${JSON.stringify(withoutContent.map((ref) => ({ component: ref.component, sourcePath: ref.sourcePath })))}\n\`\`\``);
29
+ }
30
+ return sections;
31
+ }
@@ -0,0 +1,4 @@
1
+ import type { Skill } from '../../../types/prompt.js';
2
+ export declare function resolveSkillPath(skill: Skill): string;
3
+ export declare function formatCustomPromptBanner(skill: 'components' | 'select', path: string): string;
4
+ export declare function readSkillFile(skill: Skill, override?: string): Promise<string>;
@@ -0,0 +1,49 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ const SKILL_FILES = {
6
+ components: 'generate-components.md',
7
+ tokens: 'generate-tokens.md',
8
+ select: 'select-components.md',
9
+ 'map-tokens': 'map-tokens.md',
10
+ };
11
+ export function resolveSkillPath(skill) {
12
+ if (!(skill in SKILL_FILES))
13
+ throw new Error(`Invalid skill: ${skill}`);
14
+ const thisDir = dirname(fileURLToPath(import.meta.url));
15
+ let dir = thisDir;
16
+ for (;;) {
17
+ const candidate = join(dir, 'skills');
18
+ if (existsSync(candidate))
19
+ return join(candidate, SKILL_FILES[skill]);
20
+ const parent = resolve(dir, '..');
21
+ if (parent === dir) {
22
+ throw new Error(`skill file missing from CLI installation (could not locate skills/ directory from: ${thisDir})`);
23
+ }
24
+ dir = parent;
25
+ }
26
+ }
27
+ export function formatCustomPromptBanner(skill, path) {
28
+ return (`WARNING: Custom prompt active for ${skill}: ${path}\n` +
29
+ ` Bundled invariants (utility-wrapper rejection, description content rules) do NOT apply.\n` +
30
+ ` You are responsible for the prompt's correctness.\n`);
31
+ }
32
+ export async function readSkillFile(skill, override) {
33
+ if (override) {
34
+ const skillPath = resolve(override);
35
+ try {
36
+ return await readFile(skillPath, 'utf8');
37
+ }
38
+ catch {
39
+ throw new Error(`custom prompt file not found (skill: ${skill}, path: ${skillPath})`);
40
+ }
41
+ }
42
+ const skillPath = resolveSkillPath(skill);
43
+ try {
44
+ return await readFile(skillPath, 'utf8');
45
+ }
46
+ catch {
47
+ throw new Error(`skill file missing from CLI installation — try reinstalling the CLI (looked for: ${skillPath})`);
48
+ }
49
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-generation",
3
- "version": "2.35.1-dev-build-35ec3f8d.0",
3
+ "version": "2.35.1-dev-build-9605c7ee.0",
4
4
  "description": "Agent-invocation and skill-prompt engine for the Contentful Experience Design System SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
22
22
  "skills/"
23
23
  ],
24
24
  "dependencies": {
25
- "@contentful/experience-design-system-types": "2.35.1-dev-build-35ec3f8d.0"
25
+ "@contentful/experience-design-system-types": "2.35.1-dev-build-9605c7ee.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@tsconfig/node24": "^24.0.4",