@salesforce/b2c-dx-mcp 2.0.0 → 2.1.1

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.
Files changed (124) hide show
  1. package/README.md +15 -62
  2. package/dist/commands/mcp.d.ts +1 -0
  3. package/dist/commands/mcp.js +41 -9
  4. package/dist/registry.d.ts +3 -4
  5. package/dist/registry.js +7 -14
  6. package/dist/server.d.ts +1 -1
  7. package/dist/server.js +3 -1
  8. package/dist/services.d.ts +21 -1
  9. package/dist/services.js +39 -6
  10. package/dist/tools/adapter.d.ts +18 -2
  11. package/dist/tools/adapter.js +49 -10
  12. package/dist/tools/cartridges/index.js +16 -22
  13. package/dist/tools/diagnostics/config-inspect.js +4 -8
  14. package/dist/tools/diagnostics/debug-capture-at-breakpoint.js +3 -9
  15. package/dist/tools/diagnostics/debug-list-sessions.js +1 -0
  16. package/dist/tools/diagnostics/debug-start-session.js +16 -9
  17. package/dist/tools/diagnostics/debug-wait-for-stop.js +1 -3
  18. package/dist/tools/diagnostics/log-watch-registry.d.ts +3 -0
  19. package/dist/tools/diagnostics/log-watch-registry.js +1 -0
  20. package/dist/tools/diagnostics/logs-get-recent.js +2 -5
  21. package/dist/tools/diagnostics/logs-list-files.js +1 -1
  22. package/dist/tools/diagnostics/logs-watch-list.js +1 -0
  23. package/dist/tools/diagnostics/logs-watch-start.js +10 -10
  24. package/dist/tools/diagnostics/mrt-log-watch-registry.d.ts +3 -0
  25. package/dist/tools/diagnostics/mrt-log-watch-registry.js +0 -0
  26. package/dist/tools/diagnostics/mrt-logs-watch-list.js +1 -0
  27. package/dist/tools/diagnostics/mrt-logs-watch-poll.js +2 -5
  28. package/dist/tools/diagnostics/mrt-logs-watch-start.js +9 -8
  29. package/dist/tools/diagnostics/session-registry.d.ts +3 -0
  30. package/dist/tools/diagnostics/session-registry.js +2 -1
  31. package/dist/tools/docs/docs-list.js +4 -6
  32. package/dist/tools/docs/docs-read.js +2 -9
  33. package/dist/tools/docs/docs-schema-list.js +1 -1
  34. package/dist/tools/docs/docs-schema-read.js +2 -3
  35. package/dist/tools/docs/docs-schema-search.js +2 -2
  36. package/dist/tools/docs/docs-search.js +3 -9
  37. package/dist/tools/docs/storefront.js +3 -3
  38. package/dist/tools/docs/topics.js +3 -1
  39. package/dist/tools/index.d.ts +0 -1
  40. package/dist/tools/index.js +0 -1
  41. package/dist/tools/mrt/index.js +6 -2
  42. package/dist/tools/project-context.d.ts +38 -11
  43. package/dist/tools/project-context.js +32 -15
  44. package/dist/tools/pwav3/pwa-kit-development-guidelines.js +3 -43
  45. package/dist/tools/scapi/metrics-get.js +5 -23
  46. package/dist/tools/scapi/scapi-custom-api-generate-scaffold.d.ts +4 -0
  47. package/dist/tools/scapi/scapi-custom-api-generate-scaffold.js +29 -14
  48. package/dist/tools/scapi/scapi-custom-apis-get-status.js +3 -14
  49. package/dist/tools/scapi/scapi-schemas-list.js +11 -11
  50. package/dist/utils/constants.d.ts +2 -13
  51. package/dist/utils/constants.js +1 -20
  52. package/oclif.manifest.json +2 -2
  53. package/package.json +5 -5
  54. package/content/sfnext/auth.md +0 -62
  55. package/content/sfnext/components.md +0 -123
  56. package/content/sfnext/config.md +0 -180
  57. package/content/sfnext/data-fetching.md +0 -323
  58. package/content/sfnext/extensions.md +0 -80
  59. package/content/sfnext/i18n.md +0 -121
  60. package/content/sfnext/page-designer.md +0 -78
  61. package/content/sfnext/performance.md +0 -80
  62. package/content/sfnext/pitfalls.md +0 -141
  63. package/content/sfnext/quick-reference.md +0 -226
  64. package/content/sfnext/state-management.md +0 -75
  65. package/content/sfnext/styling.md +0 -51
  66. package/content/sfnext/testing.md +0 -232
  67. package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.d.ts +0 -24
  68. package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.js +0 -53
  69. package/dist/tools/storefrontnext/figma/figma-to-component/index.d.ts +0 -45
  70. package/dist/tools/storefrontnext/figma/figma-to-component/index.js +0 -332
  71. package/dist/tools/storefrontnext/figma/generate-component/decision.d.ts +0 -40
  72. package/dist/tools/storefrontnext/figma/generate-component/decision.js +0 -312
  73. package/dist/tools/storefrontnext/figma/generate-component/formatter.d.ts +0 -9
  74. package/dist/tools/storefrontnext/figma/generate-component/formatter.js +0 -92
  75. package/dist/tools/storefrontnext/figma/generate-component/index.d.ts +0 -117
  76. package/dist/tools/storefrontnext/figma/generate-component/index.js +0 -102
  77. package/dist/tools/storefrontnext/figma/map-tokens/css-parser.d.ts +0 -71
  78. package/dist/tools/storefrontnext/figma/map-tokens/css-parser.js +0 -260
  79. package/dist/tools/storefrontnext/figma/map-tokens/index.d.ts +0 -64
  80. package/dist/tools/storefrontnext/figma/map-tokens/index.js +0 -242
  81. package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.d.ts +0 -65
  82. package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.js +0 -268
  83. package/dist/tools/storefrontnext/index.d.ts +0 -30
  84. package/dist/tools/storefrontnext/index.js +0 -28
  85. package/dist/tools/storefrontnext/page-designer-decorator/analyzer.d.ts +0 -169
  86. package/dist/tools/storefrontnext/page-designer-decorator/analyzer.js +0 -567
  87. package/dist/tools/storefrontnext/page-designer-decorator/index.d.ts +0 -259
  88. package/dist/tools/storefrontnext/page-designer-decorator/index.js +0 -622
  89. package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.d.ts +0 -8
  90. package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.js +0 -65
  91. package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.d.ts +0 -13
  92. package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.js +0 -87
  93. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.d.ts +0 -4
  94. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.js +0 -55
  95. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.d.ts +0 -22
  96. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.js +0 -109
  97. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.d.ts +0 -21
  98. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.js +0 -60
  99. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.d.ts +0 -27
  100. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.js +0 -68
  101. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.d.ts +0 -4
  102. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.js +0 -65
  103. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.d.ts +0 -11
  104. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.js +0 -92
  105. package/dist/tools/storefrontnext/page-designer-decorator/rules.d.ts +0 -51
  106. package/dist/tools/storefrontnext/page-designer-decorator/rules.js +0 -70
  107. package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.d.ts +0 -116
  108. package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.js +0 -350
  109. package/dist/tools/storefrontnext/sfnext-development-guidelines.d.ts +0 -9
  110. package/dist/tools/storefrontnext/sfnext-development-guidelines.js +0 -141
  111. package/dist/tools/storefrontnext/site-theming/color-contrast.d.ts +0 -92
  112. package/dist/tools/storefrontnext/site-theming/color-contrast.js +0 -186
  113. package/dist/tools/storefrontnext/site-theming/color-mapping.d.ts +0 -16
  114. package/dist/tools/storefrontnext/site-theming/color-mapping.js +0 -131
  115. package/dist/tools/storefrontnext/site-theming/guidance-merger.d.ts +0 -11
  116. package/dist/tools/storefrontnext/site-theming/guidance-merger.js +0 -78
  117. package/dist/tools/storefrontnext/site-theming/index.d.ts +0 -14
  118. package/dist/tools/storefrontnext/site-theming/index.js +0 -128
  119. package/dist/tools/storefrontnext/site-theming/response-builder.d.ts +0 -16
  120. package/dist/tools/storefrontnext/site-theming/response-builder.js +0 -316
  121. package/dist/tools/storefrontnext/site-theming/theming-store.d.ts +0 -64
  122. package/dist/tools/storefrontnext/site-theming/theming-store.js +0 -417
  123. package/dist/tools/storefrontnext/site-theming/types.d.ts +0 -36
  124. package/dist/tools/storefrontnext/site-theming/types.js +0 -7
@@ -1,128 +0,0 @@
1
- /*
2
- * Copyright (c) 2025, Salesforce, Inc.
3
- * SPDX-License-Identifier: Apache-2
4
- * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
- */
6
- /**
7
- * Site Theming tool for Storefront Next.
8
- *
9
- * Provides theming guidelines, guided questions, and automatic WCAG color contrast
10
- * validation. Call this tool first when users request brand colors or theme changes.
11
- *
12
- * @module tools/storefrontnext/site-theming
13
- */
14
- import { z } from 'zod';
15
- import { createToolAdapter, textResult, errorResult } from '../../adapter.js';
16
- import { projectDirectoryInput } from '../../project-context.js';
17
- import { siteThemingStore } from './theming-store.js';
18
- import { mergeGuidance } from './guidance-merger.js';
19
- import { generateResponse } from './response-builder.js';
20
- /**
21
- * Creates the site theming MCP tool for Storefront Next.
22
- *
23
- * The tool guides theming changes (colors, fonts, visual styling) and validates color
24
- * combinations for WCAG accessibility. It must be called before implementing any
25
- * theming changes.
26
- *
27
- * @param loadServices - Function that loads configuration and returns Services instance
28
- * @returns The configured MCP tool
29
- */
30
- export function createSiteThemingTool(loadServices) {
31
- return createToolAdapter({
32
- name: 'sfnext_configure_theme',
33
- description: '[DEPRECATED] Superseded by the storefront-next and storefront-next-figma agent-skills plugins and NOT compatible with the Storefront Next 1.0 GA release. Will be removed in a future release. ' +
34
- '⚠️ MANDATORY: Call this tool FIRST before implementing any theming changes. ' +
35
- 'Provides theming guidelines, questions, and automatic validation. ' +
36
- 'CRITICAL RULES: Call immediately when user requests theming (even if colors/fonts provided). ' +
37
- 'NEVER implement without calling this tool first. NEVER skip question-answer workflow. ' +
38
- 'MUST ask questions and WAIT for responses. ' +
39
- 'VALIDATION GATE: After collecting answers, call tool again with colorMapping to trigger validation. ' +
40
- 'DEFAULT FILES: theming-questions, theming-validation, theming-accessibility. ' +
41
- 'Use fileKeys to add custom files. ' +
42
- 'WORKFLOW: Call tool → Ask questions → Call with colorMapping (validation) → Present findings → Wait confirmation → Implement',
43
- toolsets: ['STOREFRONTNEXT_DEPRECATED'],
44
- isGA: false,
45
- requiresInstance: false,
46
- usesProjectContext: true,
47
- inputSchema: {
48
- projectDirectory: projectDirectoryInput,
49
- fileKeys: z
50
- .array(z.string())
51
- .optional()
52
- .describe('Array of file keys to add to the default set. If provided, guidance from all specified files will be merged with defaults: theming-questions, theming-validation, theming-accessibility. Available keys can be listed by calling the tool without parameters.'),
53
- conversationContext: z
54
- .object({
55
- currentStep: z
56
- .string()
57
- .optional()
58
- .describe('Current step in the theming conversation (e.g., "collecting-colors", "collecting-fonts")'),
59
- collectedAnswers: z
60
- .record(z.string(), z.any())
61
- .optional()
62
- .describe('Previously collected answers from the user'),
63
- questionsAsked: z.array(z.string()).optional().describe('List of questions that have already been asked'),
64
- })
65
- .optional()
66
- .describe('Context from previous conversation rounds'),
67
- },
68
- async execute(args, context) {
69
- siteThemingStore.initialize(context.services.resolveWithProjectDirectory(undefined, args.projectDirectory), {
70
- themingFiles: context.services.getEnvironmentVariable('THEMING_FILES'),
71
- });
72
- const defaultFileKeys = ['theming-questions', 'theming-validation', 'theming-accessibility'];
73
- let fileKeys;
74
- if (args.fileKeys && args.fileKeys.length > 0) {
75
- const allKeys = [...defaultFileKeys, ...args.fileKeys];
76
- fileKeys = [...new Set(allKeys)];
77
- }
78
- else {
79
- fileKeys = defaultFileKeys;
80
- }
81
- const hasContext = args.conversationContext &&
82
- (args.conversationContext.collectedAnswers ||
83
- args.conversationContext.questionsAsked ||
84
- args.conversationContext.currentStep);
85
- if (!args.fileKeys && !hasContext) {
86
- const availableKeys = siteThemingStore.getKeys();
87
- if (availableKeys.length === 0) {
88
- return {
89
- text: 'No theming files have been loaded. Please ensure theming files are configured at server startup.',
90
- isError: false,
91
- };
92
- }
93
- return {
94
- text: `Available theming files:\n\n${availableKeys.map((key) => `- ${key}`).join('\n')}\n\nDefault files (always used): theming-questions, theming-validation, theming-accessibility\n\nUse the \`fileKeys\` parameter to add additional files. User-provided files are merged with the defaults.`,
95
- isError: false,
96
- };
97
- }
98
- const guidanceArray = [];
99
- const missingKeys = [];
100
- for (const key of fileKeys) {
101
- const guidance = siteThemingStore.get(key);
102
- if (guidance) {
103
- guidanceArray.push(guidance);
104
- }
105
- else {
106
- missingKeys.push(key);
107
- }
108
- }
109
- if (guidanceArray.length === 0 || missingKeys.length > 0) {
110
- const availableKeys = siteThemingStore.getKeys();
111
- const keysList = fileKeys.length === 1 ? `key "${fileKeys[0]}"` : `keys: ${fileKeys.join(', ')}`;
112
- const missingList = missingKeys.length === 1 ? `"${missingKeys[0]}"` : missingKeys.join(', ');
113
- return {
114
- text: `Theming file(s) with ${keysList} not found.\n\nMissing: ${missingList}\nAvailable keys: ${availableKeys.join(', ')}\n\nFiles are loaded at server startup. To add more files, configure them via the THEMING_FILES environment variable or update the server initialization.`,
115
- isError: true,
116
- };
117
- }
118
- const guidance = fileKeys.length > 1 ? mergeGuidance(guidanceArray) : guidanceArray[0];
119
- const response = generateResponse(guidance, args.conversationContext);
120
- return {
121
- text: response,
122
- isError: false,
123
- };
124
- },
125
- formatOutput: (output) => output.isError ? errorResult(output.text) : textResult(output.text),
126
- }, loadServices);
127
- }
128
- //# sourceMappingURL=index.js.map
@@ -1,16 +0,0 @@
1
- /**
2
- * Builds the theming tool response from guidance and conversation context.
3
- *
4
- * @module tools/storefrontnext/site-theming/response-builder
5
- */
6
- import type { ThemingGuidance } from './theming-store.js';
7
- import type { ConversationContext } from './types.js';
8
- /**
9
- * Returns questions relevant to the current conversation state, filtered and sorted.
10
- */
11
- export declare function getRelevantQuestions(guidance: ThemingGuidance, context?: ConversationContext): ThemingGuidance['questions'];
12
- export declare function hasProvidedThemingInfo(context?: ConversationContext): boolean;
13
- /**
14
- * Generates the full theming tool response from guidance and conversation context.
15
- */
16
- export declare function generateResponse(guidance: ThemingGuidance, context?: ConversationContext): string;
@@ -1,316 +0,0 @@
1
- /*
2
- * Copyright (c) 2025, Salesforce, Inc.
3
- * SPDX-License-Identifier: Apache-2
4
- * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
- */
6
- import { buildColorCombinations, appendValidationSection } from './color-mapping.js';
7
- function isComponentScopeQuestion(question) {
8
- const questionLower = question.question.toLowerCase();
9
- return (questionLower.includes('which components') ||
10
- questionLower.includes('component scope') ||
11
- questionLower.includes('component group'));
12
- }
13
- /**
14
- * Returns questions relevant to the current conversation state, filtered and sorted.
15
- */
16
- export function getRelevantQuestions(guidance, context) {
17
- if (!context || !context.questionsAsked || context.questionsAsked.length === 0) {
18
- return guidance.questions
19
- .filter((q) => !isComponentScopeQuestion(q))
20
- .sort((a, b) => {
21
- if (a.required !== b.required) {
22
- return a.required ? -1 : 1;
23
- }
24
- const categoryOrder = { colors: 0, typography: 1, general: 2 };
25
- return ((categoryOrder[a.category] || 2) -
26
- (categoryOrder[b.category] || 2));
27
- });
28
- }
29
- const askedIds = new Set(context.questionsAsked);
30
- const remaining = guidance.questions.filter((q) => !askedIds.has(q.id) && !isComponentScopeQuestion(q));
31
- if (context.collectedAnswers) {
32
- const followUps = [];
33
- for (const q of remaining) {
34
- if (q.followUpQuestions && context.collectedAnswers?.[q.id]) {
35
- for (const [index, followUp] of q.followUpQuestions.entries()) {
36
- followUps.push({
37
- id: `${q.id}-followup-${index}`,
38
- question: followUp,
39
- category: q.category,
40
- required: false,
41
- });
42
- }
43
- }
44
- }
45
- return [...remaining, ...followUps];
46
- }
47
- return remaining;
48
- }
49
- export function hasProvidedThemingInfo(context) {
50
- if (!context?.collectedAnswers) {
51
- return false;
52
- }
53
- const collectedAnswers = context.collectedAnswers;
54
- const hasColors = Boolean(collectedAnswers.colors && Array.isArray(collectedAnswers.colors));
55
- const hasFonts = Boolean(collectedAnswers.fonts && Array.isArray(collectedAnswers.fonts));
56
- return hasColors || hasFonts;
57
- }
58
- function buildExtractionResponse(extractionInstructions) {
59
- const internal = '# ⚠️ MANDATORY: Extract User-Provided Theming Information\n\n## 🚨 CRITICAL: Information Extraction Required\n\n' +
60
- extractionInstructions;
61
- const user = "I need to extract the theming information from your input first.\n\nLet me review what you've shared and structure it properly, then I'll proceed with clarifying questions.\n\n";
62
- return `${internal}\n\n---\n\n# USER-FACING RESPONSE (What to say to the user):\n\n${user}`;
63
- }
64
- function appendValidationInstructions(out, validation) {
65
- let s = out +
66
- '## ⚠️ MANDATORY: Input Validation\n\n**BEFORE implementing, you MUST validate ALL user-provided inputs:**\n\n';
67
- if (validation.colorValidation)
68
- s +=
69
- '**A. Color Combination Validation (MANDATORY if colors provided):**\n\n' + validation.colorValidation + '\n\n';
70
- if (validation.fontValidation)
71
- s += '**B. Font Validation (MANDATORY if fonts provided):**\n\n' + validation.fontValidation + '\n\n';
72
- if (validation.generalValidation)
73
- s += '**C. General Input Validation:**\n\n' + validation.generalValidation + '\n\n';
74
- if (validation.requirements)
75
- s += '**IMPORTANT:**\n\n' + validation.requirements + '\n\n';
76
- return s;
77
- }
78
- function appendCriticalAndRules(out, guidance) {
79
- let s = out;
80
- const critical = guidance.guidelines.filter((g) => g.critical);
81
- if (critical.length > 0) {
82
- s += '## ⚠️ Critical Guidelines (INTERNAL - Follow these rules)\n\n';
83
- for (const g of critical)
84
- s += `### ${g.title}\n\n${g.content}\n\n`;
85
- }
86
- if (guidance.rules.length > 0) {
87
- s += '## Rules to Follow (INTERNAL)\n\n';
88
- const doRules = guidance.rules.filter((r) => r.type === 'do');
89
- const dontRules = guidance.rules.filter((r) => r.type === 'dont');
90
- if (doRules.length > 0) {
91
- s += '### ✅ What TO Do:\n\n';
92
- for (const r of doRules)
93
- s += `- ${r.description}\n`;
94
- s += '\n';
95
- }
96
- if (dontRules.length > 0) {
97
- s += '### ❌ What NOT to Do:\n\n';
98
- for (const r of dontRules)
99
- s += `- ${r.description}\n`;
100
- s += '\n';
101
- }
102
- }
103
- return s;
104
- }
105
- function extractColorsFromArray(colors) {
106
- if (!colors || !Array.isArray(colors))
107
- return [];
108
- const out = [];
109
- for (const color of colors) {
110
- if (color.hex && color.type)
111
- out.push(`${color.hex} (${color.type})`);
112
- else if (color.hex)
113
- out.push(color.hex);
114
- }
115
- return out;
116
- }
117
- function extractFontsFromArray(fonts) {
118
- if (!fonts || !Array.isArray(fonts))
119
- return [];
120
- const out = [];
121
- for (const font of fonts) {
122
- if (font.name)
123
- out.push(font.type ? `${font.name} (${font.type})` : font.name);
124
- }
125
- return out;
126
- }
127
- function extractColorFromValue(value) {
128
- if (typeof value === 'string')
129
- return value;
130
- if (typeof value === 'object' && value && 'hex' in value) {
131
- const v = value;
132
- if (v.hex === undefined)
133
- return null;
134
- return v.type ? `${v.hex} (${v.type})` : v.hex;
135
- }
136
- return null;
137
- }
138
- function extractFontFromValue(value) {
139
- if (typeof value === 'string')
140
- return value;
141
- if (typeof value === 'object' && value && 'name' in value) {
142
- const v = value;
143
- if (v.name === undefined)
144
- return null;
145
- return v.type ? `${v.name} (${v.type})` : v.name;
146
- }
147
- return null;
148
- }
149
- function shouldSkipKeyForOtherInfo(key, lowerKey) {
150
- if (key === 'colors' || key === 'fonts')
151
- return true;
152
- if (lowerKey.includes('question') || lowerKey.includes('step'))
153
- return true;
154
- if (lowerKey.includes('color') || lowerKey.includes('font'))
155
- return true;
156
- return false;
157
- }
158
- function extractOtherInfoFromEntries(collectedAnswers) {
159
- const otherInfo = [];
160
- for (const key of Object.keys(collectedAnswers)) {
161
- const lowerKey = key.toLowerCase();
162
- if (shouldSkipKeyForOtherInfo(key, lowerKey))
163
- continue;
164
- const value = collectedAnswers[key];
165
- if (value === null || value === undefined)
166
- continue;
167
- otherInfo.push(`${key}: ${typeof value === 'object' ? JSON.stringify(value) : value}`);
168
- }
169
- return otherInfo;
170
- }
171
- function collectUserInfo(collectedAnswers) {
172
- const colorsInfo = [...extractColorsFromArray(collectedAnswers.colors)];
173
- const fontsInfo = [...extractFontsFromArray(collectedAnswers.fonts)];
174
- for (const key of Object.keys(collectedAnswers)) {
175
- const lowerKey = key.toLowerCase();
176
- const value = collectedAnswers[key];
177
- if (key === 'colors' || key === 'fonts' || lowerKey.includes('question') || lowerKey.includes('step'))
178
- continue;
179
- if (lowerKey.includes('color') && !key.includes('colors')) {
180
- const c = extractColorFromValue(value);
181
- if (c)
182
- colorsInfo.push(c);
183
- continue;
184
- }
185
- if (lowerKey.includes('font') && !key.includes('fonts')) {
186
- const f = extractFontFromValue(value);
187
- if (f)
188
- fontsInfo.push(f);
189
- continue;
190
- }
191
- }
192
- const otherInfo = extractOtherInfoFromEntries(collectedAnswers);
193
- return { colorsInfo, fontsInfo, otherInfo };
194
- }
195
- function buildUserInfoSection(info) {
196
- const { colorsInfo, fontsInfo, otherInfo } = info;
197
- if (colorsInfo.length === 0 && fontsInfo.length === 0 && otherInfo.length === 0) {
198
- return 'Following the theming workflow. I need a few clarifications before implementing.\n\n';
199
- }
200
- let s = "## Information You've Provided\n\n";
201
- if (colorsInfo.length > 0) {
202
- s += '### Colors:\n';
203
- for (const c of colorsInfo)
204
- s += `- ${c}\n`;
205
- s += '\n';
206
- }
207
- if (fontsInfo.length > 0) {
208
- s += '### Fonts:\n';
209
- for (const f of fontsInfo)
210
- s += `- ${f}\n`;
211
- s += '\n';
212
- }
213
- if (otherInfo.length > 0) {
214
- s += '### Other Information:\n';
215
- for (const o of otherInfo)
216
- s += `- ${o}\n`;
217
- s += '\n';
218
- }
219
- return (s +
220
- "I've noted the information above. Before implementing, I need a few clarifications to ensure everything is set up correctly.\n\n");
221
- }
222
- function buildInternalInstructionsBase(guidance, context) {
223
- let s = '# ⚠️ MANDATORY: Site Theming Guidelines and Questions\n\n## 🚨 CRITICAL: Read This First\n\n';
224
- if (guidance.workflow?.steps && guidance.workflow.steps.length > 0) {
225
- s += '**YOU MUST FOLLOW THIS WORKFLOW - NO EXCEPTIONS:**\n\n';
226
- for (const [i, step] of guidance.workflow.steps.entries())
227
- s += `${i + 1}. ${step}\n`;
228
- s += '\n**VIOLATION OF THIS WORKFLOW IS A CRITICAL ERROR.**\n\n';
229
- }
230
- if (guidance.validation)
231
- s = appendValidationInstructions(s, guidance.validation);
232
- const colorMapping = context?.collectedAnswers?.colorMapping;
233
- if (colorMapping && Object.keys(colorMapping).length > 0) {
234
- s +=
235
- '## 🎨 AUTOMATED COLOR VALIDATION RESULTS\n\n**The following validation has been automatically performed using built-in contrast calculation:**\n\n';
236
- s = appendValidationSection(s, buildColorCombinations(colorMapping));
237
- }
238
- return appendCriticalAndRules(s, guidance);
239
- }
240
- function appendQuestionsToResponse(internal, user, nextQuestions, relevantQuestions) {
241
- let userOut = user + '## Questions\n\n';
242
- const categories = [
243
- { category: 'colors', title: 'Color Questions' },
244
- { category: 'typography', title: 'Font Questions' },
245
- { category: 'general', title: 'General Questions' },
246
- ];
247
- for (const { category, title } of categories) {
248
- const qs = nextQuestions.filter((q) => q.category === category);
249
- if (qs.length > 0) {
250
- userOut += `### ${title}\n\n`;
251
- for (const [i, q] of qs.entries())
252
- userOut += `**Question ${i + 1}**: ${q.question}\n\n`;
253
- }
254
- }
255
- const remaining = relevantQuestions.length - nextQuestions.length;
256
- if (remaining > 0)
257
- userOut += `\n_Note: I have ${remaining} more question${remaining > 1 ? 's' : ''} to ask after you answer these._\n\n`;
258
- userOut += 'Please answer these questions so I can proceed with the implementation.\n\n';
259
- let internalOut = internal +
260
- "## Questions to Ask the User\n\n**IMPORTANT**: Ask these questions ONE AT A TIME and WAIT for the user's response before proceeding.\n\n**CRITICAL RULE**: NEVER implement changes after asking questions without waiting for the user's response.\n\n";
261
- internalOut += `**You have ${relevantQuestions.length} total questions to ask. Show ${nextQuestions.length} now, then continue with the rest after user responds.**\n\n`;
262
- for (const [i, q] of nextQuestions.entries()) {
263
- internalOut += `### Question ${i + 1} (${q.category}): ${q.id}\n\n${q.question}\n\n`;
264
- if (q.required)
265
- internalOut += '**Required**: Yes\n\n';
266
- }
267
- return { internal: internalOut, user: userOut };
268
- }
269
- function appendReadyOrWarningToResponse(internal, user, guidance, context) {
270
- const required = guidance.questions.filter((q) => q.required);
271
- const answered = required.filter((q) => context.collectedAnswers?.[q.id] !== undefined);
272
- if (answered.length < required.length) {
273
- return {
274
- internal: internal +
275
- '## ⚠️ WARNING: Not all required questions have been answered!\n\n**DO NOT implement yet. Continue asking questions.**\n\n',
276
- user: user + 'I still need answers to some required questions before I can proceed.\n\n',
277
- };
278
- }
279
- let internalOut = internal;
280
- if (guidance.workflow?.preImplementationChecklist) {
281
- internalOut +=
282
- '## ⚠️ MANDATORY PRE-IMPLEMENTATION CHECKLIST\n\n' + guidance.workflow.preImplementationChecklist + '\n\n';
283
- }
284
- const userOut = user +
285
- '## Ready to Implement\n\nI have collected all necessary information. Before implementing, I will validate all provided inputs (colors, fonts, etc.) for accessibility, availability, and best practices.\n\n';
286
- return { internal: internalOut, user: userOut };
287
- }
288
- /**
289
- * Generates the full theming tool response from guidance and conversation context.
290
- */
291
- export function generateResponse(guidance, context) {
292
- const isFirstCall = !context || !context.questionsAsked || context.questionsAsked.length === 0;
293
- if (isFirstCall && !hasProvidedThemingInfo(context) && guidance.workflow?.extractionInstructions) {
294
- return buildExtractionResponse(guidance.workflow.extractionInstructions);
295
- }
296
- const relevantQuestions = getRelevantQuestions(guidance, context);
297
- const questionLimit = !context || context.questionsAsked?.length === 0 ? 5 : 3;
298
- const nextQuestions = relevantQuestions.slice(0, questionLimit);
299
- let internalInstructions = buildInternalInstructionsBase(guidance, context);
300
- const info = context?.collectedAnswers
301
- ? collectUserInfo(context.collectedAnswers)
302
- : { colorsInfo: [], fontsInfo: [], otherInfo: [] };
303
- let userResponse = buildUserInfoSection(info);
304
- if (nextQuestions.length > 0) {
305
- const appended = appendQuestionsToResponse(internalInstructions, userResponse, nextQuestions, relevantQuestions);
306
- internalInstructions = appended.internal;
307
- userResponse = appended.user;
308
- }
309
- else if (context?.collectedAnswers && Object.keys(context.collectedAnswers).length > 0) {
310
- const appended = appendReadyOrWarningToResponse(internalInstructions, userResponse, guidance, context);
311
- internalInstructions = appended.internal;
312
- userResponse = appended.user;
313
- }
314
- return `${internalInstructions}\n\n---\n\n# USER-FACING RESPONSE (What to say to the user):\n\n${userResponse}`;
315
- }
316
- //# sourceMappingURL=response-builder.js.map
@@ -1,64 +0,0 @@
1
- export interface ThemingGuidance {
2
- questions: Array<{
3
- id: string;
4
- question: string;
5
- category: string;
6
- required: boolean;
7
- followUpQuestions?: string[];
8
- }>;
9
- guidelines: Array<{
10
- category: string;
11
- title: string;
12
- content: string;
13
- critical: boolean;
14
- }>;
15
- rules: Array<{
16
- type: 'do' | 'dont';
17
- description: string;
18
- examples?: string[];
19
- }>;
20
- workflow?: {
21
- steps: string[];
22
- extractionInstructions?: string;
23
- preImplementationChecklist?: string;
24
- };
25
- validation?: {
26
- colorValidation?: string;
27
- fontValidation?: string;
28
- generalValidation?: string;
29
- requirements?: string;
30
- };
31
- metadata: {
32
- filePath: string;
33
- fileName: string;
34
- loadedAt: Date;
35
- };
36
- }
37
- /**
38
- * Theming Data Store
39
- * Loads and caches theming guidance from .md/.mdc files
40
- */
41
- export interface InitializeOptions {
42
- /** Override content directory for default files (used in tests). */
43
- contentDirOverride?: string;
44
- /** Project-scoped THEMING_FILES value. */
45
- themingFiles?: string;
46
- }
47
- declare class ThemingStore {
48
- private initializedForRoot;
49
- private store;
50
- get(fileKey: string): ThemingGuidance | undefined;
51
- getKeys(): string[];
52
- has(fileKey: string): boolean;
53
- /**
54
- * Initialize store with default files from content/site-theming.
55
- * Uses workspaceRoot for THEMING_FILES env paths (relative to project).
56
- * Skips re-loading when already initialized for the same root.
57
- */
58
- initialize(workspaceRoot?: string, options?: InitializeOptions): void;
59
- loadFile(fileKey: string, filePath: string): void;
60
- private loadThemingFilesFromEnv;
61
- private tryLoadEnvFile;
62
- }
63
- export declare const siteThemingStore: ThemingStore;
64
- export {};