@sberbusiness/triplex-next-mcp-server 1.46.0-beta → 1.48.0-beta
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/README.md +7 -7
- package/bundle/components/AmountField.md +222 -323
- package/bundle/components/Avatar.md +138 -146
- package/bundle/components/CardStatic.md +402 -0
- package/bundle/components/CheckboxTree.md +157 -215
- package/bundle/components/CheckboxTreeExtended.md +7 -7
- package/bundle/components/ChipGroup.md +1 -1
- package/bundle/components/ChipMonthYearPicker.md +4 -4
- package/bundle/components/ChipSuggest.md +7 -6
- package/bundle/components/CollapsibleTree.md +8 -4
- package/bundle/components/CollapsibleTreeExtended.md +8 -6
- package/bundle/components/Confirm.md +346 -281
- package/bundle/components/DateRange.md +351 -210
- package/bundle/components/FooterPage.md +1 -0
- package/bundle/components/FormField.md +11 -4
- package/bundle/components/FormGroup.md +3 -2
- package/bundle/components/LightBox.md +8 -0
- package/bundle/components/ListMaster.md +2 -2
- package/bundle/components/ListTableItem.md +6 -6
- package/bundle/components/MonthYearField.md +15 -4
- package/bundle/components/Slider.md +389 -97
- package/bundle/components/SliderRange.md +486 -105
- package/bundle/components/StatusTracker.md +386 -94
- package/bundle/components/Stepper.md +355 -102
- package/bundle/components/StepperExtended.md +633 -0
- package/bundle/components/SuggestField.md +1049 -96
- package/bundle/components/SwipeableArea.md +7 -7
- package/bundle/components/Tabs.md +265 -92
- package/bundle/components/TabsExtended.md +18 -18
- package/bundle/components/TabsLine.md +301 -127
- package/bundle/components/TagColor.md +187 -66
- package/bundle/components/TagGroup.md +184 -48
- package/bundle/components/TextareaField.md +278 -70
- package/bundle/components/TopOverlay.md +17 -1
- package/bundle/components/TreeView.md +16 -7
- package/bundle/components/TriggerClickOnKeyDownEvent.md +277 -0
- package/bundle/components/UploadZone.md +318 -0
- package/bundle/guides/codestyle.md +16 -1
- package/bundle/guides/commits.md +47 -1
- package/bundle/guides/tests.md +23 -2
- package/bundle/manifest.json +48 -21
- package/bundle/release-notes/1.47.0.mdx +115 -0
- package/bundle/release-notes/1.48.0.mdx +68 -0
- package/bundle/release-notes/1.49.0.mdx +7 -0
- package/bundle/tokens.json +3 -3
- package/dist/index.js +220 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -192,6 +192,215 @@ function loadBundle() {
|
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
// src/tools/component.ts
|
|
196
|
+
var MAX_CHUNK = 2e4;
|
|
197
|
+
var SHORT_EXAMPLE_MAX = 6500;
|
|
198
|
+
var EXAMPLES_SECTION = "\u041F\u0440\u0438\u043C\u0435\u0440\u044B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F";
|
|
199
|
+
var REFERENCE_SECTIONS = /* @__PURE__ */ new Set([
|
|
200
|
+
"\u0414\u0438\u0437\u0430\u0439\u043D-\u0442\u043E\u043A\u0435\u043D\u044B",
|
|
201
|
+
"\u0421\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0435 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u044B",
|
|
202
|
+
"Stories",
|
|
203
|
+
"\u0418\u0441\u0442\u043E\u0440\u0438\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439",
|
|
204
|
+
"\u0424\u0430\u0439\u043B\u043E\u0432\u0430\u044F \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0430",
|
|
205
|
+
"\u041A\u043B\u044E\u0447\u0435\u0432\u044B\u0435 \u043E\u0441\u043E\u0431\u0435\u043D\u043D\u043E\u0441\u0442\u0438 \u0440\u0435\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438",
|
|
206
|
+
EXAMPLES_SECTION
|
|
207
|
+
]);
|
|
208
|
+
var SUBSECTION_HEADING_RE = /^###\s+(.+?)\s*$/;
|
|
209
|
+
var FENCE_RE = /^\s*```/;
|
|
210
|
+
var TRAILING_RULE_RE = /\n+-{3,}\s*$/;
|
|
211
|
+
function paginate(text, offset) {
|
|
212
|
+
if (text.length - offset <= MAX_CHUNK) {
|
|
213
|
+
return { body: text.slice(offset), next: null };
|
|
214
|
+
}
|
|
215
|
+
const hardEnd = offset + MAX_CHUNK;
|
|
216
|
+
const newline = text.lastIndexOf("\n", hardEnd - 1);
|
|
217
|
+
const end = newline > offset + MAX_CHUNK / 2 ? newline + 1 : hardEnd;
|
|
218
|
+
return { body: text.slice(offset, end), next: end };
|
|
219
|
+
}
|
|
220
|
+
function extractSubsections(text) {
|
|
221
|
+
const result = {};
|
|
222
|
+
let current = null;
|
|
223
|
+
let buffer = [];
|
|
224
|
+
let inFence = false;
|
|
225
|
+
const flush = () => {
|
|
226
|
+
if (current !== null) {
|
|
227
|
+
result[current] = buffer.join("\n").trim();
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
for (const line of text.split("\n")) {
|
|
231
|
+
if (FENCE_RE.test(line)) {
|
|
232
|
+
inFence = !inFence;
|
|
233
|
+
}
|
|
234
|
+
const match = inFence ? null : SUBSECTION_HEADING_RE.exec(line);
|
|
235
|
+
if (match) {
|
|
236
|
+
flush();
|
|
237
|
+
current = match[1];
|
|
238
|
+
buffer = [];
|
|
239
|
+
} else if (current !== null) {
|
|
240
|
+
buffer.push(line);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
flush();
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
function sectionText(text) {
|
|
247
|
+
return text.replace(TRAILING_RULE_RE, "").trim();
|
|
248
|
+
}
|
|
249
|
+
function findKey(record, wanted) {
|
|
250
|
+
const needle = wanted.trim().toLowerCase();
|
|
251
|
+
return Object.keys(record).find((key) => key.toLowerCase() === needle);
|
|
252
|
+
}
|
|
253
|
+
function quoteList(names) {
|
|
254
|
+
return names.map((name) => JSON.stringify(name)).join(", ");
|
|
255
|
+
}
|
|
256
|
+
function callHint(name, args) {
|
|
257
|
+
return `get_component ${JSON.stringify({ name, ...args })}`;
|
|
258
|
+
}
|
|
259
|
+
function metaLine(component) {
|
|
260
|
+
const parts = [];
|
|
261
|
+
if (component.category) {
|
|
262
|
+
parts.push(`\u041A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u044F: ${component.category}`);
|
|
263
|
+
}
|
|
264
|
+
if (component.related.length > 0) {
|
|
265
|
+
parts.push(`\u0421\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0435: ${component.related.join(", ")}`);
|
|
266
|
+
}
|
|
267
|
+
if (component.figma.file || component.figma.node) {
|
|
268
|
+
parts.push(`Figma: ${[component.figma.file, component.figma.node].filter(Boolean).join(", ")}`);
|
|
269
|
+
}
|
|
270
|
+
if (component.tokens.length > 0) {
|
|
271
|
+
parts.push(
|
|
272
|
+
`\u0422\u043E\u043A\u0435\u043D\u044B (${component.tokens.length}): get_tokens ${JSON.stringify({ component: component.name })}`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
return parts.length > 0 ? parts.join(" \xB7 ") : null;
|
|
276
|
+
}
|
|
277
|
+
function pickShortExample(examples) {
|
|
278
|
+
const fitting = Object.keys(examples).filter((key) => examples[key].length <= SHORT_EXAMPLE_MAX);
|
|
279
|
+
if (fitting.length === 0) {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
const byDefault = fitting.find((key) => key.toLowerCase() === "default");
|
|
283
|
+
if (byDefault) {
|
|
284
|
+
return byDefault;
|
|
285
|
+
}
|
|
286
|
+
return fitting.reduce((best, key) => examples[key].length < examples[best].length ? key : best);
|
|
287
|
+
}
|
|
288
|
+
function buildCompact(component) {
|
|
289
|
+
const { sections } = component;
|
|
290
|
+
const parts = [`# ${component.name}`];
|
|
291
|
+
const meta = metaLine(component);
|
|
292
|
+
if (meta) {
|
|
293
|
+
parts.push(meta);
|
|
294
|
+
}
|
|
295
|
+
for (const [title, text] of Object.entries(sections)) {
|
|
296
|
+
if (!REFERENCE_SECTIONS.has(title)) {
|
|
297
|
+
parts.push(`## ${title}
|
|
298
|
+
|
|
299
|
+
${sectionText(text)}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const examples = extractSubsections(sections[EXAMPLES_SECTION] ?? "");
|
|
303
|
+
const shown = pickShortExample(examples);
|
|
304
|
+
if (shown) {
|
|
305
|
+
parts.push(`## \u041F\u0440\u0438\u043C\u0435\u0440: ${shown}
|
|
306
|
+
|
|
307
|
+
${examples[shown]}`);
|
|
308
|
+
}
|
|
309
|
+
const moreSections = Object.keys(sections).filter((title) => REFERENCE_SECTIONS.has(title) && title !== EXAMPLES_SECTION).map((title) => `${JSON.stringify(title)} ${sectionText(sections[title]).length}`);
|
|
310
|
+
const moreExamples = Object.keys(examples).filter((title) => title !== shown).map((title) => `${JSON.stringify(title)} ${examples[title].length}`);
|
|
311
|
+
const more = [
|
|
312
|
+
"## \u0415\u0449\u0451\n",
|
|
313
|
+
"\u042D\u0442\u043E \u043A\u043E\u043C\u043F\u0430\u043A\u0442\u043D\u044B\u0439 \u043E\u0442\u0432\u0435\u0442. \u041E\u0441\u0442\u0430\u043B\u044C\u043D\u043E\u0435 \u2014 \u0442\u0435\u043C \u0436\u0435 get_component, \u043E\u0434\u043D\u0438\u043C \u0438\u0437 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432 (\u0440\u0430\u0437\u043C\u0435\u0440 \u0432 \u0441\u0438\u043C\u0432\u043E\u043B\u0430\u0445):"
|
|
314
|
+
];
|
|
315
|
+
if (moreSections.length > 0) {
|
|
316
|
+
more.push(`- section: ${moreSections.join(", ")}`);
|
|
317
|
+
}
|
|
318
|
+
if (moreExamples.length > 0) {
|
|
319
|
+
more.push(`- example: ${moreExamples.join(", ")}`);
|
|
320
|
+
}
|
|
321
|
+
more.push(`- full: true \u2014 \u0432\u0435\u0441\u044C AI.md, ${(component.markdown ?? "").length}`);
|
|
322
|
+
parts.push(more.join("\n"));
|
|
323
|
+
return parts.join("\n\n");
|
|
324
|
+
}
|
|
325
|
+
function buildFallback(component) {
|
|
326
|
+
const stories = component.stories ? ` Stories: \`${component.stories}\`.` : "";
|
|
327
|
+
return `# ${component.name}
|
|
328
|
+
|
|
329
|
+
AI-\u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u0438 \u0443 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430 \u043D\u0435\u0442 (ai_ready: false).${stories}`;
|
|
330
|
+
}
|
|
331
|
+
function selectPiece(component, query) {
|
|
332
|
+
const { sections } = component;
|
|
333
|
+
if (query.section !== void 0) {
|
|
334
|
+
const key = findKey(sections, query.section);
|
|
335
|
+
if (key === void 0) {
|
|
336
|
+
return {
|
|
337
|
+
ok: false,
|
|
338
|
+
text: `\u0421\u0435\u043A\u0446\u0438\u0438 ${JSON.stringify(query.section)} \u0443 ${component.name} \u043D\u0435\u0442. \u0415\u0441\u0442\u044C: ${quoteList(Object.keys(sections))}.`
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
return { ok: true, text: `## ${key}
|
|
342
|
+
|
|
343
|
+
${sectionText(sections[key])}`, args: { section: key } };
|
|
344
|
+
}
|
|
345
|
+
if (query.example !== void 0) {
|
|
346
|
+
const examples = extractSubsections(sections[EXAMPLES_SECTION] ?? "");
|
|
347
|
+
const key = findKey(examples, query.example);
|
|
348
|
+
if (key === void 0) {
|
|
349
|
+
const names = Object.keys(examples);
|
|
350
|
+
return {
|
|
351
|
+
ok: false,
|
|
352
|
+
text: names.length > 0 ? `\u041F\u0440\u0438\u043C\u0435\u0440\u0430 ${JSON.stringify(query.example)} \u0443 ${component.name} \u043D\u0435\u0442. \u0415\u0441\u0442\u044C: ${quoteList(names)}.` : `\u0423 ${component.name} \u043D\u0435\u0442 \u0441\u0435\u043A\u0446\u0438\u0438 \xAB${EXAMPLES_SECTION}\xBB.`
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
return { ok: true, text: `### ${key}
|
|
356
|
+
|
|
357
|
+
${examples[key]}`, args: { example: key } };
|
|
358
|
+
}
|
|
359
|
+
if (query.full) {
|
|
360
|
+
const meta = metaLine(component);
|
|
361
|
+
const body = component.markdown ?? "";
|
|
362
|
+
return { ok: true, text: meta ? `${meta}
|
|
363
|
+
|
|
364
|
+
${body}` : body, args: { full: true } };
|
|
365
|
+
}
|
|
366
|
+
return { ok: true, text: buildCompact(component), args: {} };
|
|
367
|
+
}
|
|
368
|
+
function buildComponentResponse(component, query = {}) {
|
|
369
|
+
const selectors = [query.section !== void 0, query.example !== void 0, query.full === true];
|
|
370
|
+
if (selectors.filter(Boolean).length > 1) {
|
|
371
|
+
return { ok: false, text: "\u0423\u043A\u0430\u0436\u0438 \u043D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 \u043E\u0434\u043D\u043E\u0433\u043E \u0438\u0437 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432: section, example, full." };
|
|
372
|
+
}
|
|
373
|
+
if (!component.ai_ready) {
|
|
374
|
+
return { ok: true, text: buildFallback(component) };
|
|
375
|
+
}
|
|
376
|
+
const piece = selectPiece(component, query);
|
|
377
|
+
if (!piece.ok) {
|
|
378
|
+
return piece;
|
|
379
|
+
}
|
|
380
|
+
const offset = query.offset ?? 0;
|
|
381
|
+
if (offset > 0 && offset >= piece.text.length) {
|
|
382
|
+
return {
|
|
383
|
+
ok: false,
|
|
384
|
+
text: `offset ${offset} \u0437\u0430 \u043A\u043E\u043D\u0446\u043E\u043C \u043E\u0442\u0432\u0435\u0442\u0430: \u0432 \u043D\u0451\u043C ${piece.text.length} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432.`
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
const chunk = paginate(piece.text, offset);
|
|
388
|
+
const end = offset + chunk.body.length;
|
|
389
|
+
const lines = [];
|
|
390
|
+
if (offset > 0) {
|
|
391
|
+
lines.push(`\u2014 \u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0435\u043D\u0438\u0435: \u0441\u0438\u043C\u0432\u043E\u043B\u044B ${offset}\u2013${end} \u0438\u0437 ${piece.text.length} \u2014
|
|
392
|
+
`);
|
|
393
|
+
}
|
|
394
|
+
lines.push(chunk.body);
|
|
395
|
+
if (chunk.next !== null) {
|
|
396
|
+
lines.push(
|
|
397
|
+
`
|
|
398
|
+
\u2014 \u041F\u043E\u043A\u0430\u0437\u0430\u043D\u044B \u0441\u0438\u043C\u0432\u043E\u043B\u044B ${offset}\u2013${end} \u0438\u0437 ${piece.text.length}. \u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0435\u043D\u0438\u0435: ${callHint(component.name, { ...piece.args, offset: chunk.next })} \u2014`
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
return { ok: true, text: lines.join("\n") };
|
|
402
|
+
}
|
|
403
|
+
|
|
195
404
|
// src/tools/guidelines.ts
|
|
196
405
|
var GUIDELINES_TOPIC = "guidelines";
|
|
197
406
|
function buildGuidelinesResponse(bundle) {
|
|
@@ -362,9 +571,15 @@ function registerTools(server) {
|
|
|
362
571
|
);
|
|
363
572
|
server.tool(
|
|
364
573
|
"get_component",
|
|
365
|
-
"\
|
|
366
|
-
{
|
|
367
|
-
|
|
574
|
+
"\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430. \u041F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u2014 \u043A\u043E\u043C\u043F\u0430\u043A\u0442\u043D\u0430\u044F: \u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435, props, \u0438\u043D\u0432\u0430\u0440\u0438\u0430\u043D\u0442\u044B, accessibility, \u043E\u0434\u0438\u043D \u043A\u043E\u0440\u043E\u0442\u043A\u0438\u0439 \u043F\u0440\u0438\u043C\u0435\u0440 \u0438 \u043E\u0433\u043B\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043E\u0441\u0442\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u0441 \u0440\u0430\u0437\u043C\u0435\u0440\u0430\u043C\u0438. \u0421\u043F\u0440\u0430\u0432\u043E\u0447\u043D\u0443\u044E \u0441\u0435\u043A\u0446\u0438\u044E, \u0434\u0440\u0443\u0433\u043E\u0439 \u043F\u0440\u0438\u043C\u0435\u0440 \u0438\u043B\u0438 \u0432\u0435\u0441\u044C AI.md \u2014 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u043C section, example \u0438\u043B\u0438 full; \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u043E\u0442\u0432\u0435\u0442 \u043F\u0440\u0438\u0445\u043E\u0434\u0438\u0442 \u043F\u043E\u0440\u0446\u0438\u044F\u043C\u0438 \u0441 \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u043E\u0439 offset.",
|
|
575
|
+
{
|
|
576
|
+
name: z.string().describe("\u0418\u043C\u044F \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 'Button'"),
|
|
577
|
+
section: z.string().optional().describe("\u041E\u0434\u043D\u0430 \u0441\u0435\u043A\u0446\u0438\u044F AI.md \u0446\u0435\u043B\u0438\u043A\u043E\u043C, \u043D\u0430\u043F\u0440. '\u0414\u0438\u0437\u0430\u0439\u043D-\u0442\u043E\u043A\u0435\u043D\u044B' (\u0441\u043F\u0438\u0441\u043E\u043A \u2014 \u0432 \u043E\u0433\u043B\u0430\u0432\u043B\u0435\u043D\u0438\u0438)."),
|
|
578
|
+
example: z.string().optional().describe("\u041E\u0434\u0438\u043D \u043F\u0440\u0438\u043C\u0435\u0440 \u0438\u0437 \xAB\u041F\u0440\u0438\u043C\u0435\u0440\u044B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F\xBB \u043F\u043E \u0438\u043C\u0435\u043D\u0438, \u043D\u0430\u043F\u0440. 'States'."),
|
|
579
|
+
full: z.boolean().optional().describe("\u0412\u0435\u0441\u044C AI.md \u043E\u0434\u043D\u0438\u043C \u0442\u0435\u043A\u0441\u0442\u043E\u043C, \u043F\u043E\u0440\u0446\u0438\u044F\u043C\u0438."),
|
|
580
|
+
offset: z.number().int().nonnegative().optional().describe("\u0421\u043C\u0435\u0449\u0435\u043D\u0438\u0435 \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u043D\u043E\u0433\u043E \u043E\u0442\u0432\u0435\u0442\u0430 \u2014 \u0438\u0437 \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0438 \u0432 \u043A\u043E\u043D\u0446\u0435 \u043F\u043E\u0440\u0446\u0438\u0438.")
|
|
581
|
+
},
|
|
582
|
+
async ({ name, section, example, full, offset }) => {
|
|
368
583
|
const component = bundle.components.find((c) => c.name.toLowerCase() === name.toLowerCase());
|
|
369
584
|
if (!component) {
|
|
370
585
|
return {
|
|
@@ -377,9 +592,8 @@ function registerTools(server) {
|
|
|
377
592
|
isError: true
|
|
378
593
|
};
|
|
379
594
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
};
|
|
595
|
+
const result = buildComponentResponse(component, { section, example, full, offset });
|
|
596
|
+
return result.ok ? { content: [{ type: "text", text: result.text }] } : { content: [{ type: "text", text: result.text }], isError: true };
|
|
383
597
|
}
|
|
384
598
|
);
|
|
385
599
|
server.tool(
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/tools/index.ts","../src/parsers/loader.ts","../src/parsers/parseComponent.ts","../src/tools/guidelines.ts","../src/tools/tokens.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main() {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"Triplex MCP Server started\");\n}\n\nmain().catch((error) => {\n console.error(\"Failed to start server:\", error);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { registerTools } from \"./tools/index.js\";\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: \"triplex\",\n version: \"0.1.0\",\n });\n\n registerTools(server);\n\n return server;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { loadBundle, loadIcons } from \"../parsers/loader.js\";\nimport { buildGuidelinesResponse } from \"./guidelines.js\";\nimport { buildTokensResponse } from \"./tokens.js\";\n\nexport function registerTools(server: McpServer): void {\n const bundle = loadBundle();\n const icons = loadIcons();\n const availableIconSizes = Array.from(new Set(icons.icons.map((i) => i.size))).sort(\n (a, b) => a - b,\n );\n\n server.tool(\n \"list_components\",\n \"Список всех компонентов дизайн-системы Triplex с кратким описанием и флагом ai_ready.\",\n {},\n async () => {\n const list = bundle.components.map((c) => ({\n name: c.name,\n description: c.description,\n category: c.category,\n ai_ready: c.ai_ready,\n }));\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(list, null, 2) }],\n };\n },\n );\n\n server.tool(\n \"get_component\",\n \"Полная документация компонента: назначение, props, токены, инварианты, accessibility, секции AI.md.\",\n { name: z.string().describe(\"Имя компонента, например 'Button'\") },\n async ({ name }) => {\n const component = bundle.components.find((c) => c.name.toLowerCase() === name.toLowerCase());\n\n if (!component) {\n return {\n content: [\n {\n type: \"text\",\n text: `Компонент \"${name}\" не найден. Используйте list_components для списка доступных компонентов.`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(component, null, 2) }],\n };\n },\n );\n\n server.tool(\n \"get_tokens\",\n \"Дизайн-токены Triplex: пути `Группа.Токен` для ThemeProvider, значения светлой и тёмной темы, ссылки на палитру. Без аргументов — индекс групп.\",\n {\n component: z\n .string()\n .optional()\n .describe(\"Имя компонента: вернуть токены, которые он использует. Напр. 'Calendar'.\"),\n group: z\n .string()\n .optional()\n .describe(\"Имя группы токенов: вернуть всю группу целиком. Напр. 'ColorBrand'.\"),\n },\n async ({ component, group }) => {\n const result = buildTokensResponse(bundle, { component, group });\n\n return result.ok\n ? { content: [{ type: \"text\", text: JSON.stringify(result.payload, null, 2) }] }\n : { content: [{ type: \"text\", text: result.text }], isError: true };\n },\n );\n\n server.tool(\n \"get_guidelines\",\n \"Гайдлайны кодогенерации на Triplex для ИИ-агентов: правила TPX-G-NN — какие компоненты использовать для текстов, сетки, отступов, иконок, обвязка приложения. Прочитай перед генерацией кода по макету.\",\n {},\n async () => {\n const result = buildGuidelinesResponse(bundle);\n\n return result.ok\n ? { content: [{ type: \"text\", text: result.text }] }\n : { content: [{ type: \"text\", text: result.text }], isError: true };\n },\n );\n\n server.tool(\n \"list_icons\",\n \"Список доступных иконок из @sberbusiness/icons-next. Используй перед тем как импортировать иконку, чтобы не придумать несуществующее имя. Фильтрация по подстроке в имени и по размеру.\",\n {\n query: z\n .string()\n .optional()\n .describe(\n \"Подстрока для поиска в имени иконки (регистронезависимая). Напр. 'plus' или 'arrow'.\",\n ),\n size: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Размер иконки в px (см. availableSizes в ответе для доступных значений).\"),\n limit: z\n .number()\n .int()\n .positive()\n .max(500)\n .optional()\n .describe(\"Максимум иконок в ответе. По умолчанию 100.\"),\n },\n async ({ query, size, limit }) => {\n if (icons.icons.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Список иконок пуст — сервер не смог загрузить bundle/icons.json. Проверь, что 'npm run fetch-icons' отработал на этапе сборки.\",\n },\n ],\n isError: true,\n };\n }\n\n const needle = query?.trim().toLowerCase() ?? \"\";\n const max = limit ?? 100;\n\n const matched = icons.icons.filter((ic) => {\n if (size !== undefined && ic.size !== size) return false;\n if (needle && !ic.name.toLowerCase().includes(needle)) return false;\n return true;\n });\n\n const truncated = matched.length > max;\n const page = truncated ? matched.slice(0, max) : matched;\n\n const payload = {\n package: `${icons.packageName}@${icons.packageVersion}`,\n totalInBundle: icons.icons.length,\n matched: matched.length,\n returned: page.length,\n truncated,\n availableSizes: availableIconSizes,\n icons: page,\n usage: \"import { IconName } from '@sberbusiness/icons-next'; <IconName />\",\n };\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n };\n },\n );\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n IconsBundle,\n Manifest,\n ParsedBundle,\n RawComponent,\n TokensSection,\n} from \"../types/index.js\";\nimport { parseComponent } from \"./parseComponent.js\";\n\nconst EMPTY_BUNDLE: ParsedBundle = {\n schemaVersion: 1,\n triplexVersion: \"0.0.0\",\n generatedAt: new Date(0).toISOString(),\n components: [],\n guides: [],\n releaseNotes: [],\n tokens: null,\n};\n\nconst EMPTY_ICONS: IconsBundle = {\n schemaVersion: 1,\n packageName: \"@sberbusiness/icons-next\",\n packageVersion: \"0.0.0\",\n generatedAt: new Date(0).toISOString(),\n icons: [],\n};\n\n/**\n * Tsup bundles всю source в `dist/index.js`, поэтому относительный путь\n * src/parsers/loader.ts → bundle/... не совпадает с runtime-путём.\n * Идём вверх до ближайшего `package.json` — так корень пакета находится\n * и в dev (tsx/vitest из src/), и в prod (bundled dist/), и после npm-install.\n */\nfunction findPackageRoot(startDir: string): string {\n let dir = startDir;\n while (dir !== dirname(dir)) {\n if (existsSync(resolve(dir, \"package.json\"))) {\n return dir;\n }\n dir = dirname(dir);\n }\n throw new Error(`package.json not found above ${startDir}`);\n}\n\nconst PACKAGE_ROOT = findPackageRoot(dirname(fileURLToPath(import.meta.url)));\nconst BUNDLE_DIR = resolve(PACKAGE_ROOT, \"bundle\");\nconst MANIFEST_PATH = resolve(BUNDLE_DIR, \"manifest.json\");\nconst ICONS_PATH = resolve(BUNDLE_DIR, \"icons.json\");\n\nexport function loadIcons(): IconsBundle {\n try {\n return JSON.parse(readFileSync(ICONS_PATH, \"utf-8\")) as IconsBundle;\n } catch {\n console.error(`Failed to load icons from ${ICONS_PATH}. Run 'npm run fetch-icons' first.`);\n return EMPTY_ICONS;\n }\n}\n\n/**\n * Читает дерево дизайн-токенов. null — bundle собран до schemaVersion 2\n * (или файл не разложен): tools в этом случае работают без значений токенов.\n */\nfunction loadTokens(manifest: Manifest): TokensSection | null {\n if (!manifest.tokens) {\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(resolve(BUNDLE_DIR, manifest.tokens), \"utf-8\")) as TokensSection;\n } catch {\n console.error(\n `Failed to load tokens from ${manifest.tokens}. Run 'npm run fetch-bundle' first.`,\n );\n return null;\n }\n}\n\nexport function loadBundle(): ParsedBundle {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(readFileSync(MANIFEST_PATH, \"utf-8\")) as Manifest;\n } catch {\n console.error(\n `Failed to load manifest from ${MANIFEST_PATH}. Run 'npm run fetch-bundle' first.`,\n );\n return EMPTY_BUNDLE;\n }\n\n return {\n schemaVersion: manifest.schemaVersion,\n triplexVersion: manifest.triplexVersion,\n generatedAt: manifest.generatedAt,\n components: manifest.components.map((mc) => {\n const raw: RawComponent =\n mc.file !== null\n ? {\n name: mc.name,\n path: mc.path,\n raw: readFileSync(resolve(BUNDLE_DIR, mc.file), \"utf-8\"),\n examples: [],\n fallback: null,\n }\n : {\n name: mc.name,\n path: mc.path,\n raw: null,\n examples: [],\n fallback: {\n name: mc.name,\n storiesPath: mc.storiesPath ?? null,\n },\n };\n return parseComponent(raw);\n }),\n guides: manifest.guides.map((g) => ({\n topic: g.topic,\n path: g.path,\n raw: readFileSync(resolve(BUNDLE_DIR, g.file), \"utf-8\"),\n })),\n releaseNotes: manifest.releaseNotes.map((n) => ({\n version: n.version,\n path: n.path,\n raw: readFileSync(resolve(BUNDLE_DIR, n.file), \"utf-8\"),\n })),\n tokens: loadTokens(manifest),\n };\n}\n","import matter from \"gray-matter\";\nimport type { ComponentFrontmatter, ParsedComponent, RawComponent } from \"../types/index.js\";\n\nconst SECTION_HEADING_RE = /^##\\s+(.+?)\\s*$/;\n\nexport function parseComponent(raw: RawComponent): ParsedComponent {\n if (raw.raw === null) {\n const fallback = raw.fallback ?? { name: raw.name, storiesPath: null };\n return {\n name: raw.name,\n path: raw.path,\n ai_ready: false,\n category: null,\n description: null,\n figma: { file: null, node: null },\n related: [],\n tokens: [],\n stories: fallback.storiesPath,\n sections: {},\n markdown: null,\n };\n }\n\n const parsed = matter(raw.raw);\n const fm = parsed.data as ComponentFrontmatter;\n const body = parsed.content;\n const sections = extractSections(body);\n\n return {\n name: raw.name,\n path: raw.path,\n ai_ready: true,\n category: fm.category ?? null,\n description: extractDescription(sections),\n figma: {\n file: nonEmpty(fm[\"figma-file\"]),\n node: nonEmpty(fm[\"figma-node\"]),\n },\n related: Array.isArray(fm.related) ? fm.related : [],\n tokens: Array.isArray(fm.tokens) ? fm.tokens : [],\n stories: fm.stories ?? null,\n sections,\n markdown: body,\n };\n}\n\nfunction extractSections(body: string): Record<string, string> {\n const sections: Record<string, string> = {};\n let currentTitle: string | null = null;\n let buffer: string[] = [];\n\n const flush = () => {\n if (currentTitle !== null) {\n sections[currentTitle] = buffer.join(\"\\n\").trim();\n }\n };\n\n for (const line of body.split(\"\\n\")) {\n const match = SECTION_HEADING_RE.exec(line);\n if (match) {\n flush();\n currentTitle = match[1];\n buffer = [];\n } else if (currentTitle !== null) {\n buffer.push(line);\n }\n }\n flush();\n return sections;\n}\n\nfunction extractDescription(sections: Record<string, string>): string | null {\n const purpose = sections[\"Назначение\"];\n if (!purpose) {\n return null;\n }\n const firstParagraph = purpose\n .split(/\\n\\s*\\n/)\n .map((p) => p.trim())\n .find((p) => p.length > 0);\n return firstParagraph ?? null;\n}\n\nfunction nonEmpty(value: string | undefined): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n","/**\n * Сборка ответа tool `get_guidelines`.\n *\n * Гайдлайны кодогенерации (`docs/mcp/guidelines.md` в triplex-next, правила\n * `TPX-G-NN`) приезжают через bundle как guide с топиком `guidelines` —\n * начиная с triplex-next 1.45.0. На более старом bundle топика нет: сервер\n * обязан работать и в этом случае, отвечая внятной ошибкой, а не падая.\n */\nimport type { ParsedBundle } from \"../types/index.js\";\n\nexport const GUIDELINES_TOPIC = \"guidelines\";\n\nexport type GuidelinesResult = { ok: true; text: string } | { ok: false; text: string };\n\nexport function buildGuidelinesResponse(bundle: ParsedBundle): GuidelinesResult {\n const guide = bundle.guides.find((g) => g.topic === GUIDELINES_TOPIC);\n\n if (!guide) {\n return {\n ok: false,\n text:\n `Bundle собран из triplex-next ${bundle.triplexVersion} и гайдлайнов не содержит — ` +\n \"они поставляются начиная с 1.45.0. Обновите bundle: npm run fetch-bundle.\",\n };\n }\n\n return { ok: true, text: guide.raw };\n}\n","/**\n * Сборка ответа tool `get_tokens`.\n *\n * Токены Triplex адресуются путём `Группа.Токен` — ровно в этом виде они\n * передаются в `ThemeProvider` через prop `tokens`. CSS-переменные\n * `--triplex-next-*` публичным API не являются: на сборке библиотеки к имени\n * дописывается версия пакета.\n *\n * Дерево токенов приходит в bundle начиная с `schemaVersion: 2`. Для более\n * старых bundle доступны только пути из frontmatter AI.md — ответ в этом случае\n * помечается `note`, а сервер продолжает работать.\n */\nimport type { ParsedBundle, TokenEntry, TokensSection } from \"../types/index.js\";\n\n/** Фильтры tool `get_tokens`. Оба необязательны, `group` имеет приоритет. */\nexport interface TokensQuery {\n component?: string;\n group?: string;\n}\n\nexport type TokensResult = { ok: true; payload: unknown } | { ok: false; text: string };\n\nexport const LEGACY_NOTE =\n \"Bundle собран до schemaVersion 2 и значений токенов не содержит — доступны только пути. Обновите bundle: npm run fetch-bundle.\";\n\n/** Как потребитель переопределяет токен: единственный публичный способ. */\nfunction howToOverride(group: string) {\n return {\n api: \"<ThemeProvider tokens={...}> из @sberbusiness/triplex-next\",\n example: [\n \"const TOKENS = {\",\n ` ${group}: {`,\n ' <Токен>: {value: \"#FFFFFF\"}, // своё значение',\n ' <Другой>: {ref: \"ColorBrand.50\"}, // ссылка на core-токен',\n \" },\",\n \"};\",\n \"\",\n \"<ThemeProvider tokens={TOKENS} scopeRef={scopeRef}>…</ThemeProvider>\",\n ].join(\"\\n\"),\n notes: [\n \"Объект tokens плоский: группы лежат на верхнем уровне, вложенности core/components нет.\",\n \"Одним объектом можно переопределить несколько групп сразу — и core, и компонентные.\",\n \"ref указывает только на core-токены (refable: true).\",\n \"tokens сравнивается по ссылке — выносите объект из рендера.\",\n \"Переопределение действует внутри элемента из scopeRef.\",\n ],\n };\n}\n\n/** Внутренний слой: css-переменные с версией пакета в имени. */\nfunction internalNote(section: TokensSection) {\n return {\n cssVarPattern: section.internal.cssVarPattern,\n note: \"Внутренняя реализация: в собранном пакете к имени переменной добавляется версия, поэтому в коде потребителя использовать её нельзя.\",\n };\n}\n\n/** Core-токены, на которые ссылаются переданные токены. */\nfunction coreTokensUsed(tokens: TokenEntry[]): string[] {\n const refs = tokens.flatMap((token) =>\n [token.light.ref, token.dark.ref].filter((ref): ref is string => ref !== undefined),\n );\n\n return [...new Set(refs)].sort();\n}\n\n/** Индекс групп: имя → число токенов. Полное дерево слишком велико для одного ответа. */\nfunction groupIndex(section: TokensSection, kind: \"core\" | \"component\"): Record<string, number> {\n return Object.fromEntries(\n Object.entries(section.groups)\n .filter(([, group]) => group.kind === kind)\n .map(([name, group]) => [name, Object.keys(group.tokens).length]),\n );\n}\n\nfunction byGroup(section: TokensSection, group: string): TokensResult {\n const name = Object.keys(section.groups).find((key) => key.toLowerCase() === group.toLowerCase());\n\n if (name === undefined) {\n return {\n ok: false,\n text: `Группа токенов \"${group}\" не найдена. Список групп: get_tokens() без аргументов.`,\n };\n }\n\n const entry = section.groups[name];\n\n return {\n ok: true,\n payload: {\n group: name,\n kind: entry.kind,\n refable: entry.refable,\n tokenCount: Object.keys(entry.tokens).length,\n howToOverride: howToOverride(name),\n tokens: Object.values(entry.tokens),\n internal: internalNote(section),\n },\n };\n}\n\nfunction byComponent(\n bundle: ParsedBundle,\n section: TokensSection | null,\n component: string,\n): TokensResult {\n const found = bundle.components.find((c) => c.name.toLowerCase() === component.toLowerCase());\n\n if (!found) {\n return {\n ok: false,\n text: `Компонент \"${component}\" не найден. Используйте list_components для списка доступных компонентов.`,\n };\n }\n\n if (section === null) {\n return {\n ok: true,\n payload: { component: found.name, tokens: found.tokens, note: LEGACY_NOTE },\n };\n }\n\n // Компонент может использовать токены нескольких групп: например, поле выбора\n // красится токенами FormField, Dropdown и DropdownList сразу.\n const resolved = found.tokens.map((path) => {\n const [group, token] = path.split(\".\");\n\n return { path, entry: section.groups[group]?.tokens[token] };\n });\n const known = resolved\n .map(({ entry }) => entry)\n .filter((entry): entry is TokenEntry => entry !== undefined);\n const unknown = resolved.filter(({ entry }) => entry === undefined).map(({ path }) => path);\n const groups = [...new Set(known.map((token) => token.path.split(\".\")[0]))];\n\n return {\n ok: true,\n payload: {\n component: found.name,\n groups,\n tokenCount: known.length,\n howToOverride: howToOverride(groups[0] ?? \"Группа\"),\n tokens: known,\n // Палитра, на которую ссылаются токены компонента: перекрасив core-токен,\n // потребитель меняет вид всех компонентов, которые на него ссылаются.\n coreTokensUsed: coreTokensUsed(known),\n ...(unknown.length ? { unknownTokens: unknown } : {}),\n internal: internalNote(section),\n },\n };\n}\n\n/** Собирает ответ `get_tokens` по фильтрам. Без фильтров возвращает индекс групп. */\nexport function buildTokensResponse(bundle: ParsedBundle, query: TokensQuery): TokensResult {\n const section = bundle.tokens;\n\n if (query.group !== undefined) {\n return section === null ? { ok: false, text: LEGACY_NOTE } : byGroup(section, query.group);\n }\n\n if (query.component !== undefined) {\n return byComponent(bundle, section, query.component);\n }\n\n if (section === null) {\n return {\n ok: true,\n payload: {\n note: LEGACY_NOTE,\n components: bundle.components\n .filter((c) => c.tokens.length > 0)\n .map((c) => ({ component: c.name, tokens: c.tokens })),\n },\n };\n }\n\n return {\n ok: true,\n payload: {\n triplexVersion: bundle.triplexVersion,\n overridePath: section.overridePath,\n core: {\n description: 'Палитра и примитивы. Ссылки { ref: \"ColorBrand.50\" } резолвятся сюда.',\n groups: groupIndex(section, \"core\"),\n },\n components: { groups: groupIndex(section, \"component\") },\n hint: 'Полные данные: get_tokens({ component: \"Calendar\" }) или get_tokens({ group: \"ColorBrand\" }).',\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/tools/index.ts","../src/parsers/loader.ts","../src/parsers/parseComponent.ts","../src/tools/component.ts","../src/tools/guidelines.ts","../src/tools/tokens.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main() {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"Triplex MCP Server started\");\n}\n\nmain().catch((error) => {\n console.error(\"Failed to start server:\", error);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { registerTools } from \"./tools/index.js\";\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: \"triplex\",\n version: \"0.1.0\",\n });\n\n registerTools(server);\n\n return server;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { loadBundle, loadIcons } from \"../parsers/loader.js\";\nimport { buildComponentResponse } from \"./component.js\";\nimport { buildGuidelinesResponse } from \"./guidelines.js\";\nimport { buildTokensResponse } from \"./tokens.js\";\n\nexport function registerTools(server: McpServer): void {\n const bundle = loadBundle();\n const icons = loadIcons();\n const availableIconSizes = Array.from(new Set(icons.icons.map((i) => i.size))).sort(\n (a, b) => a - b,\n );\n\n server.tool(\n \"list_components\",\n \"Список всех компонентов дизайн-системы Triplex с кратким описанием и флагом ai_ready.\",\n {},\n async () => {\n const list = bundle.components.map((c) => ({\n name: c.name,\n description: c.description,\n category: c.category,\n ai_ready: c.ai_ready,\n }));\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(list, null, 2) }],\n };\n },\n );\n\n server.tool(\n \"get_component\",\n \"Документация компонента. По умолчанию — компактная: назначение, props, инварианты, accessibility, один короткий пример и оглавление остального с размерами. Справочную секцию, другой пример или весь AI.md — параметром section, example или full; длинный ответ приходит порциями с подсказкой offset.\",\n {\n name: z.string().describe(\"Имя компонента, например 'Button'\"),\n section: z\n .string()\n .optional()\n .describe(\"Одна секция AI.md целиком, напр. 'Дизайн-токены' (список — в оглавлении).\"),\n example: z\n .string()\n .optional()\n .describe(\"Один пример из «Примеры использования» по имени, напр. 'States'.\"),\n full: z.boolean().optional().describe(\"Весь AI.md одним текстом, порциями.\"),\n offset: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe(\"Смещение продолжения длинного ответа — из подсказки в конце порции.\"),\n },\n async ({ name, section, example, full, offset }) => {\n const component = bundle.components.find((c) => c.name.toLowerCase() === name.toLowerCase());\n\n if (!component) {\n return {\n content: [\n {\n type: \"text\",\n text: `Компонент \"${name}\" не найден. Используйте list_components для списка доступных компонентов.`,\n },\n ],\n isError: true,\n };\n }\n\n const result = buildComponentResponse(component, { section, example, full, offset });\n\n return result.ok\n ? { content: [{ type: \"text\", text: result.text }] }\n : { content: [{ type: \"text\", text: result.text }], isError: true };\n },\n );\n\n server.tool(\n \"get_tokens\",\n \"Дизайн-токены Triplex: пути `Группа.Токен` для ThemeProvider, значения светлой и тёмной темы, ссылки на палитру. Без аргументов — индекс групп.\",\n {\n component: z\n .string()\n .optional()\n .describe(\"Имя компонента: вернуть токены, которые он использует. Напр. 'Calendar'.\"),\n group: z\n .string()\n .optional()\n .describe(\"Имя группы токенов: вернуть всю группу целиком. Напр. 'ColorBrand'.\"),\n },\n async ({ component, group }) => {\n const result = buildTokensResponse(bundle, { component, group });\n\n return result.ok\n ? { content: [{ type: \"text\", text: JSON.stringify(result.payload, null, 2) }] }\n : { content: [{ type: \"text\", text: result.text }], isError: true };\n },\n );\n\n server.tool(\n \"get_guidelines\",\n \"Гайдлайны кодогенерации на Triplex для ИИ-агентов: правила TPX-G-NN — какие компоненты использовать для текстов, сетки, отступов, иконок, обвязка приложения. Прочитай перед генерацией кода по макету.\",\n {},\n async () => {\n const result = buildGuidelinesResponse(bundle);\n\n return result.ok\n ? { content: [{ type: \"text\", text: result.text }] }\n : { content: [{ type: \"text\", text: result.text }], isError: true };\n },\n );\n\n server.tool(\n \"list_icons\",\n \"Список доступных иконок из @sberbusiness/icons-next. Используй перед тем как импортировать иконку, чтобы не придумать несуществующее имя. Фильтрация по подстроке в имени и по размеру.\",\n {\n query: z\n .string()\n .optional()\n .describe(\n \"Подстрока для поиска в имени иконки (регистронезависимая). Напр. 'plus' или 'arrow'.\",\n ),\n size: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Размер иконки в px (см. availableSizes в ответе для доступных значений).\"),\n limit: z\n .number()\n .int()\n .positive()\n .max(500)\n .optional()\n .describe(\"Максимум иконок в ответе. По умолчанию 100.\"),\n },\n async ({ query, size, limit }) => {\n if (icons.icons.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Список иконок пуст — сервер не смог загрузить bundle/icons.json. Проверь, что 'npm run fetch-icons' отработал на этапе сборки.\",\n },\n ],\n isError: true,\n };\n }\n\n const needle = query?.trim().toLowerCase() ?? \"\";\n const max = limit ?? 100;\n\n const matched = icons.icons.filter((ic) => {\n if (size !== undefined && ic.size !== size) return false;\n if (needle && !ic.name.toLowerCase().includes(needle)) return false;\n return true;\n });\n\n const truncated = matched.length > max;\n const page = truncated ? matched.slice(0, max) : matched;\n\n const payload = {\n package: `${icons.packageName}@${icons.packageVersion}`,\n totalInBundle: icons.icons.length,\n matched: matched.length,\n returned: page.length,\n truncated,\n availableSizes: availableIconSizes,\n icons: page,\n usage: \"import { IconName } from '@sberbusiness/icons-next'; <IconName />\",\n };\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n };\n },\n );\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n IconsBundle,\n Manifest,\n ParsedBundle,\n RawComponent,\n TokensSection,\n} from \"../types/index.js\";\nimport { parseComponent } from \"./parseComponent.js\";\n\nconst EMPTY_BUNDLE: ParsedBundle = {\n schemaVersion: 1,\n triplexVersion: \"0.0.0\",\n generatedAt: new Date(0).toISOString(),\n components: [],\n guides: [],\n releaseNotes: [],\n tokens: null,\n};\n\nconst EMPTY_ICONS: IconsBundle = {\n schemaVersion: 1,\n packageName: \"@sberbusiness/icons-next\",\n packageVersion: \"0.0.0\",\n generatedAt: new Date(0).toISOString(),\n icons: [],\n};\n\n/**\n * Tsup bundles всю source в `dist/index.js`, поэтому относительный путь\n * src/parsers/loader.ts → bundle/... не совпадает с runtime-путём.\n * Идём вверх до ближайшего `package.json` — так корень пакета находится\n * и в dev (tsx/vitest из src/), и в prod (bundled dist/), и после npm-install.\n */\nfunction findPackageRoot(startDir: string): string {\n let dir = startDir;\n while (dir !== dirname(dir)) {\n if (existsSync(resolve(dir, \"package.json\"))) {\n return dir;\n }\n dir = dirname(dir);\n }\n throw new Error(`package.json not found above ${startDir}`);\n}\n\nconst PACKAGE_ROOT = findPackageRoot(dirname(fileURLToPath(import.meta.url)));\nconst BUNDLE_DIR = resolve(PACKAGE_ROOT, \"bundle\");\nconst MANIFEST_PATH = resolve(BUNDLE_DIR, \"manifest.json\");\nconst ICONS_PATH = resolve(BUNDLE_DIR, \"icons.json\");\n\nexport function loadIcons(): IconsBundle {\n try {\n return JSON.parse(readFileSync(ICONS_PATH, \"utf-8\")) as IconsBundle;\n } catch {\n console.error(`Failed to load icons from ${ICONS_PATH}. Run 'npm run fetch-icons' first.`);\n return EMPTY_ICONS;\n }\n}\n\n/**\n * Читает дерево дизайн-токенов. null — bundle собран до schemaVersion 2\n * (или файл не разложен): tools в этом случае работают без значений токенов.\n */\nfunction loadTokens(manifest: Manifest): TokensSection | null {\n if (!manifest.tokens) {\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(resolve(BUNDLE_DIR, manifest.tokens), \"utf-8\")) as TokensSection;\n } catch {\n console.error(\n `Failed to load tokens from ${manifest.tokens}. Run 'npm run fetch-bundle' first.`,\n );\n return null;\n }\n}\n\nexport function loadBundle(): ParsedBundle {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(readFileSync(MANIFEST_PATH, \"utf-8\")) as Manifest;\n } catch {\n console.error(\n `Failed to load manifest from ${MANIFEST_PATH}. Run 'npm run fetch-bundle' first.`,\n );\n return EMPTY_BUNDLE;\n }\n\n return {\n schemaVersion: manifest.schemaVersion,\n triplexVersion: manifest.triplexVersion,\n generatedAt: manifest.generatedAt,\n components: manifest.components.map((mc) => {\n const raw: RawComponent =\n mc.file !== null\n ? {\n name: mc.name,\n path: mc.path,\n raw: readFileSync(resolve(BUNDLE_DIR, mc.file), \"utf-8\"),\n examples: [],\n fallback: null,\n }\n : {\n name: mc.name,\n path: mc.path,\n raw: null,\n examples: [],\n fallback: {\n name: mc.name,\n storiesPath: mc.storiesPath ?? null,\n },\n };\n return parseComponent(raw);\n }),\n guides: manifest.guides.map((g) => ({\n topic: g.topic,\n path: g.path,\n raw: readFileSync(resolve(BUNDLE_DIR, g.file), \"utf-8\"),\n })),\n releaseNotes: manifest.releaseNotes.map((n) => ({\n version: n.version,\n path: n.path,\n raw: readFileSync(resolve(BUNDLE_DIR, n.file), \"utf-8\"),\n })),\n tokens: loadTokens(manifest),\n };\n}\n","import matter from \"gray-matter\";\nimport type { ComponentFrontmatter, ParsedComponent, RawComponent } from \"../types/index.js\";\n\nconst SECTION_HEADING_RE = /^##\\s+(.+?)\\s*$/;\n\nexport function parseComponent(raw: RawComponent): ParsedComponent {\n if (raw.raw === null) {\n const fallback = raw.fallback ?? { name: raw.name, storiesPath: null };\n return {\n name: raw.name,\n path: raw.path,\n ai_ready: false,\n category: null,\n description: null,\n figma: { file: null, node: null },\n related: [],\n tokens: [],\n stories: fallback.storiesPath,\n sections: {},\n markdown: null,\n };\n }\n\n const parsed = matter(raw.raw);\n const fm = parsed.data as ComponentFrontmatter;\n const body = parsed.content;\n const sections = extractSections(body);\n\n return {\n name: raw.name,\n path: raw.path,\n ai_ready: true,\n category: fm.category ?? null,\n description: extractDescription(sections),\n figma: {\n file: nonEmpty(fm[\"figma-file\"]),\n node: nonEmpty(fm[\"figma-node\"]),\n },\n related: Array.isArray(fm.related) ? fm.related : [],\n tokens: Array.isArray(fm.tokens) ? fm.tokens : [],\n stories: fm.stories ?? null,\n sections,\n markdown: body,\n };\n}\n\nfunction extractSections(body: string): Record<string, string> {\n const sections: Record<string, string> = {};\n let currentTitle: string | null = null;\n let buffer: string[] = [];\n\n const flush = () => {\n if (currentTitle !== null) {\n sections[currentTitle] = buffer.join(\"\\n\").trim();\n }\n };\n\n for (const line of body.split(\"\\n\")) {\n const match = SECTION_HEADING_RE.exec(line);\n if (match) {\n flush();\n currentTitle = match[1];\n buffer = [];\n } else if (currentTitle !== null) {\n buffer.push(line);\n }\n }\n flush();\n return sections;\n}\n\nfunction extractDescription(sections: Record<string, string>): string | null {\n const purpose = sections[\"Назначение\"];\n if (!purpose) {\n return null;\n }\n const firstParagraph = purpose\n .split(/\\n\\s*\\n/)\n .map((p) => p.trim())\n .find((p) => p.length > 0);\n return firstParagraph ?? null;\n}\n\nfunction nonEmpty(value: string | undefined): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n","/**\n * Сборка ответа tool `get_component`.\n *\n * Ответ — Markdown. Раньше tool отдавал JSON, в котором тело AI.md лежало\n * дважды (по секциям и целиком), и ответ большого компонента доходил до\n * 200 тыс. символов. Клиенты режут вывод инструмента (GigaCode — около\n * 25 тыс. символов), а дочитанный целиком ответ съедает контекст агента.\n *\n * По умолчанию ответ компактный: всё, что нужно для кода (назначение, props,\n * инварианты, accessibility и нестандартные для шаблона секции вроде «Состав»\n * или «Поведение»), один короткий пример и оглавление остального с размерами.\n * Справочные секции, остальные примеры и весь AI.md запрашиваются параметрами;\n * длинный кусок отдаётся порциями по `MAX_CHUNK` символов с подсказкой, как\n * получить продолжение.\n */\nimport type { ParsedComponent } from \"../types/index.js\";\n\n/** Параметры tool `get_component` помимо имени. `section`, `example`, `full` — взаимоисключающие. */\nexport interface ComponentQuery {\n section?: string;\n example?: string;\n full?: boolean;\n offset?: number;\n}\n\nexport type ComponentResult = { ok: true; text: string } | { ok: false; text: string };\n\n/** Максимум символов в одной порции ответа — с запасом под порог клиентов в ~25 тыс. */\nexport const MAX_CHUNK = 20_000;\n\n/**\n * Пример попадает в компактный ответ, только если он не длиннее. Порог с\n * расчётом на `Default` составного компонента: у `LightBox` он 6,2 тыс. и\n * показывает, как собираются `Content`, `Page` и `Controls`.\n */\nexport const SHORT_EXAMPLE_MAX = 6_500;\n\nexport const EXAMPLES_SECTION = \"Примеры использования\";\n\n/**\n * Справочные секции AI.md: в компактном ответе они только в оглавлении.\n * Список закрытый намеренно — секция с новым заголовком по умолчанию считается\n * частью API и попадает в ответ: лишние символы дешевле потерянного props.\n */\nexport const REFERENCE_SECTIONS: ReadonlySet<string> = new Set([\n \"Дизайн-токены\",\n \"Связанные компоненты\",\n \"Stories\",\n \"История изменений\",\n \"Файловая структура\",\n \"Ключевые особенности реализации\",\n EXAMPLES_SECTION,\n]);\n\nconst SUBSECTION_HEADING_RE = /^###\\s+(.+?)\\s*$/;\nconst FENCE_RE = /^\\s*```/;\nconst TRAILING_RULE_RE = /\\n+-{3,}\\s*$/;\n\n/** Порция длинного текста: `next` — смещение продолжения, null — текст закончился. */\nexport interface Chunk {\n body: string;\n next: number | null;\n}\n\n/**\n * Режет текст на порции не длиннее `MAX_CHUNK`, стараясь закончить порцию на\n * переводе строки — чтобы не рвать строку кода или таблицы посередине.\n */\nexport function paginate(text: string, offset: number): Chunk {\n if (text.length - offset <= MAX_CHUNK) {\n return { body: text.slice(offset), next: null };\n }\n\n const hardEnd = offset + MAX_CHUNK;\n const newline = text.lastIndexOf(\"\\n\", hardEnd - 1);\n const end = newline > offset + MAX_CHUNK / 2 ? newline + 1 : hardEnd;\n return { body: text.slice(offset, end), next: end };\n}\n\n/**\n * Подсекции `### {Заголовок}` — в «Примерах использования» это отдельные\n * примеры. Заголовки внутри блоков кода не считаются.\n */\nexport function extractSubsections(text: string): Record<string, string> {\n const result: Record<string, string> = {};\n let current: string | null = null;\n let buffer: string[] = [];\n let inFence = false;\n\n const flush = () => {\n if (current !== null) {\n result[current] = buffer.join(\"\\n\").trim();\n }\n };\n\n for (const line of text.split(\"\\n\")) {\n if (FENCE_RE.test(line)) {\n inFence = !inFence;\n }\n const match = inFence ? null : SUBSECTION_HEADING_RE.exec(line);\n if (match) {\n flush();\n current = match[1];\n buffer = [];\n } else if (current !== null) {\n buffer.push(line);\n }\n }\n flush();\n return result;\n}\n\n/** Текст секции без завершающего разделителя `---`: в AI.md им закрыта каждая секция. */\nfunction sectionText(text: string): string {\n return text.replace(TRAILING_RULE_RE, \"\").trim();\n}\n\nfunction findKey(record: Record<string, string>, wanted: string): string | undefined {\n const needle = wanted.trim().toLowerCase();\n return Object.keys(record).find((key) => key.toLowerCase() === needle);\n}\n\nfunction quoteList(names: string[]): string {\n return names.map((name) => JSON.stringify(name)).join(\", \");\n}\n\nfunction callHint(name: string, args: Record<string, unknown>): string {\n return `get_component ${JSON.stringify({ name, ...args })}`;\n}\n\n/** Строка метаданных из frontmatter: категория, связанные компоненты, Figma, токены. */\nfunction metaLine(component: ParsedComponent): string | null {\n const parts: string[] = [];\n if (component.category) {\n parts.push(`Категория: ${component.category}`);\n }\n if (component.related.length > 0) {\n parts.push(`Связанные: ${component.related.join(\", \")}`);\n }\n if (component.figma.file || component.figma.node) {\n parts.push(`Figma: ${[component.figma.file, component.figma.node].filter(Boolean).join(\", \")}`);\n }\n if (component.tokens.length > 0) {\n parts.push(\n `Токены (${component.tokens.length}): get_tokens ${JSON.stringify({ component: component.name })}`,\n );\n }\n return parts.length > 0 ? parts.join(\" · \") : null;\n}\n\n/** Короткий пример для компактного ответа: `Default`, иначе самый короткий из подходящих. */\nfunction pickShortExample(examples: Record<string, string>): string | null {\n const fitting = Object.keys(examples).filter((key) => examples[key].length <= SHORT_EXAMPLE_MAX);\n if (fitting.length === 0) {\n return null;\n }\n const byDefault = fitting.find((key) => key.toLowerCase() === \"default\");\n if (byDefault) {\n return byDefault;\n }\n return fitting.reduce((best, key) => (examples[key].length < examples[best].length ? key : best));\n}\n\nfunction buildCompact(component: ParsedComponent): string {\n const { sections } = component;\n const parts: string[] = [`# ${component.name}`];\n\n const meta = metaLine(component);\n if (meta) {\n parts.push(meta);\n }\n\n for (const [title, text] of Object.entries(sections)) {\n if (!REFERENCE_SECTIONS.has(title)) {\n parts.push(`## ${title}\\n\\n${sectionText(text)}`);\n }\n }\n\n const examples = extractSubsections(sections[EXAMPLES_SECTION] ?? \"\");\n const shown = pickShortExample(examples);\n if (shown) {\n parts.push(`## Пример: ${shown}\\n\\n${examples[shown]}`);\n }\n\n const moreSections = Object.keys(sections)\n .filter((title) => REFERENCE_SECTIONS.has(title) && title !== EXAMPLES_SECTION)\n .map((title) => `${JSON.stringify(title)} ${sectionText(sections[title]).length}`);\n const moreExamples = Object.keys(examples)\n .filter((title) => title !== shown)\n .map((title) => `${JSON.stringify(title)} ${examples[title].length}`);\n\n const more = [\n \"## Ещё\\n\",\n \"Это компактный ответ. Остальное — тем же get_component, одним из параметров (размер в символах):\",\n ];\n if (moreSections.length > 0) {\n more.push(`- section: ${moreSections.join(\", \")}`);\n }\n if (moreExamples.length > 0) {\n more.push(`- example: ${moreExamples.join(\", \")}`);\n }\n more.push(`- full: true — весь AI.md, ${(component.markdown ?? \"\").length}`);\n parts.push(more.join(\"\\n\"));\n\n return parts.join(\"\\n\\n\");\n}\n\nfunction buildFallback(component: ParsedComponent): string {\n const stories = component.stories ? ` Stories: \\`${component.stories}\\`.` : \"\";\n return `# ${component.name}\\n\\nAI-документации у компонента нет (ai_ready: false).${stories}`;\n}\n\n/** Выбранный параметрами кусок AI.md или текст ошибки. */\nfunction selectPiece(\n component: ParsedComponent,\n query: ComponentQuery,\n): { ok: true; text: string; args: Record<string, unknown> } | { ok: false; text: string } {\n const { sections } = component;\n\n if (query.section !== undefined) {\n const key = findKey(sections, query.section);\n if (key === undefined) {\n return {\n ok: false,\n text: `Секции ${JSON.stringify(query.section)} у ${component.name} нет. Есть: ${quoteList(Object.keys(sections))}.`,\n };\n }\n return { ok: true, text: `## ${key}\\n\\n${sectionText(sections[key])}`, args: { section: key } };\n }\n\n if (query.example !== undefined) {\n const examples = extractSubsections(sections[EXAMPLES_SECTION] ?? \"\");\n const key = findKey(examples, query.example);\n if (key === undefined) {\n const names = Object.keys(examples);\n return {\n ok: false,\n text:\n names.length > 0\n ? `Примера ${JSON.stringify(query.example)} у ${component.name} нет. Есть: ${quoteList(names)}.`\n : `У ${component.name} нет секции «${EXAMPLES_SECTION}».`,\n };\n }\n return { ok: true, text: `### ${key}\\n\\n${examples[key]}`, args: { example: key } };\n }\n\n if (query.full) {\n const meta = metaLine(component);\n const body = component.markdown ?? \"\";\n return { ok: true, text: meta ? `${meta}\\n\\n${body}` : body, args: { full: true } };\n }\n\n return { ok: true, text: buildCompact(component), args: {} };\n}\n\nexport function buildComponentResponse(\n component: ParsedComponent,\n query: ComponentQuery = {},\n): ComponentResult {\n const selectors = [query.section !== undefined, query.example !== undefined, query.full === true];\n if (selectors.filter(Boolean).length > 1) {\n return { ok: false, text: \"Укажи не больше одного из параметров: section, example, full.\" };\n }\n\n if (!component.ai_ready) {\n return { ok: true, text: buildFallback(component) };\n }\n\n const piece = selectPiece(component, query);\n if (!piece.ok) {\n return piece;\n }\n\n const offset = query.offset ?? 0;\n if (offset > 0 && offset >= piece.text.length) {\n return {\n ok: false,\n text: `offset ${offset} за концом ответа: в нём ${piece.text.length} символов.`,\n };\n }\n\n const chunk = paginate(piece.text, offset);\n const end = offset + chunk.body.length;\n const lines: string[] = [];\n if (offset > 0) {\n lines.push(`— Продолжение: символы ${offset}–${end} из ${piece.text.length} —\\n`);\n }\n lines.push(chunk.body);\n if (chunk.next !== null) {\n lines.push(\n `\\n— Показаны символы ${offset}–${end} из ${piece.text.length}. ` +\n `Продолжение: ${callHint(component.name, { ...piece.args, offset: chunk.next })} —`,\n );\n }\n return { ok: true, text: lines.join(\"\\n\") };\n}\n","/**\n * Сборка ответа tool `get_guidelines`.\n *\n * Гайдлайны кодогенерации (`docs/mcp/guidelines.md` в triplex-next, правила\n * `TPX-G-NN`) приезжают через bundle как guide с топиком `guidelines` —\n * начиная с triplex-next 1.45.0. На более старом bundle топика нет: сервер\n * обязан работать и в этом случае, отвечая внятной ошибкой, а не падая.\n */\nimport type { ParsedBundle } from \"../types/index.js\";\n\nexport const GUIDELINES_TOPIC = \"guidelines\";\n\nexport type GuidelinesResult = { ok: true; text: string } | { ok: false; text: string };\n\nexport function buildGuidelinesResponse(bundle: ParsedBundle): GuidelinesResult {\n const guide = bundle.guides.find((g) => g.topic === GUIDELINES_TOPIC);\n\n if (!guide) {\n return {\n ok: false,\n text:\n `Bundle собран из triplex-next ${bundle.triplexVersion} и гайдлайнов не содержит — ` +\n \"они поставляются начиная с 1.45.0. Обновите bundle: npm run fetch-bundle.\",\n };\n }\n\n return { ok: true, text: guide.raw };\n}\n","/**\n * Сборка ответа tool `get_tokens`.\n *\n * Токены Triplex адресуются путём `Группа.Токен` — ровно в этом виде они\n * передаются в `ThemeProvider` через prop `tokens`. CSS-переменные\n * `--triplex-next-*` публичным API не являются: на сборке библиотеки к имени\n * дописывается версия пакета.\n *\n * Дерево токенов приходит в bundle начиная с `schemaVersion: 2`. Для более\n * старых bundle доступны только пути из frontmatter AI.md — ответ в этом случае\n * помечается `note`, а сервер продолжает работать.\n */\nimport type { ParsedBundle, TokenEntry, TokensSection } from \"../types/index.js\";\n\n/** Фильтры tool `get_tokens`. Оба необязательны, `group` имеет приоритет. */\nexport interface TokensQuery {\n component?: string;\n group?: string;\n}\n\nexport type TokensResult = { ok: true; payload: unknown } | { ok: false; text: string };\n\nexport const LEGACY_NOTE =\n \"Bundle собран до schemaVersion 2 и значений токенов не содержит — доступны только пути. Обновите bundle: npm run fetch-bundle.\";\n\n/** Как потребитель переопределяет токен: единственный публичный способ. */\nfunction howToOverride(group: string) {\n return {\n api: \"<ThemeProvider tokens={...}> из @sberbusiness/triplex-next\",\n example: [\n \"const TOKENS = {\",\n ` ${group}: {`,\n ' <Токен>: {value: \"#FFFFFF\"}, // своё значение',\n ' <Другой>: {ref: \"ColorBrand.50\"}, // ссылка на core-токен',\n \" },\",\n \"};\",\n \"\",\n \"<ThemeProvider tokens={TOKENS} scopeRef={scopeRef}>…</ThemeProvider>\",\n ].join(\"\\n\"),\n notes: [\n \"Объект tokens плоский: группы лежат на верхнем уровне, вложенности core/components нет.\",\n \"Одним объектом можно переопределить несколько групп сразу — и core, и компонентные.\",\n \"ref указывает только на core-токены (refable: true).\",\n \"tokens сравнивается по ссылке — выносите объект из рендера.\",\n \"Переопределение действует внутри элемента из scopeRef.\",\n ],\n };\n}\n\n/** Внутренний слой: css-переменные с версией пакета в имени. */\nfunction internalNote(section: TokensSection) {\n return {\n cssVarPattern: section.internal.cssVarPattern,\n note: \"Внутренняя реализация: в собранном пакете к имени переменной добавляется версия, поэтому в коде потребителя использовать её нельзя.\",\n };\n}\n\n/** Core-токены, на которые ссылаются переданные токены. */\nfunction coreTokensUsed(tokens: TokenEntry[]): string[] {\n const refs = tokens.flatMap((token) =>\n [token.light.ref, token.dark.ref].filter((ref): ref is string => ref !== undefined),\n );\n\n return [...new Set(refs)].sort();\n}\n\n/** Индекс групп: имя → число токенов. Полное дерево слишком велико для одного ответа. */\nfunction groupIndex(section: TokensSection, kind: \"core\" | \"component\"): Record<string, number> {\n return Object.fromEntries(\n Object.entries(section.groups)\n .filter(([, group]) => group.kind === kind)\n .map(([name, group]) => [name, Object.keys(group.tokens).length]),\n );\n}\n\nfunction byGroup(section: TokensSection, group: string): TokensResult {\n const name = Object.keys(section.groups).find((key) => key.toLowerCase() === group.toLowerCase());\n\n if (name === undefined) {\n return {\n ok: false,\n text: `Группа токенов \"${group}\" не найдена. Список групп: get_tokens() без аргументов.`,\n };\n }\n\n const entry = section.groups[name];\n\n return {\n ok: true,\n payload: {\n group: name,\n kind: entry.kind,\n refable: entry.refable,\n tokenCount: Object.keys(entry.tokens).length,\n howToOverride: howToOverride(name),\n tokens: Object.values(entry.tokens),\n internal: internalNote(section),\n },\n };\n}\n\nfunction byComponent(\n bundle: ParsedBundle,\n section: TokensSection | null,\n component: string,\n): TokensResult {\n const found = bundle.components.find((c) => c.name.toLowerCase() === component.toLowerCase());\n\n if (!found) {\n return {\n ok: false,\n text: `Компонент \"${component}\" не найден. Используйте list_components для списка доступных компонентов.`,\n };\n }\n\n if (section === null) {\n return {\n ok: true,\n payload: { component: found.name, tokens: found.tokens, note: LEGACY_NOTE },\n };\n }\n\n // Компонент может использовать токены нескольких групп: например, поле выбора\n // красится токенами FormField, Dropdown и DropdownList сразу.\n const resolved = found.tokens.map((path) => {\n const [group, token] = path.split(\".\");\n\n return { path, entry: section.groups[group]?.tokens[token] };\n });\n const known = resolved\n .map(({ entry }) => entry)\n .filter((entry): entry is TokenEntry => entry !== undefined);\n const unknown = resolved.filter(({ entry }) => entry === undefined).map(({ path }) => path);\n const groups = [...new Set(known.map((token) => token.path.split(\".\")[0]))];\n\n return {\n ok: true,\n payload: {\n component: found.name,\n groups,\n tokenCount: known.length,\n howToOverride: howToOverride(groups[0] ?? \"Группа\"),\n tokens: known,\n // Палитра, на которую ссылаются токены компонента: перекрасив core-токен,\n // потребитель меняет вид всех компонентов, которые на него ссылаются.\n coreTokensUsed: coreTokensUsed(known),\n ...(unknown.length ? { unknownTokens: unknown } : {}),\n internal: internalNote(section),\n },\n };\n}\n\n/** Собирает ответ `get_tokens` по фильтрам. Без фильтров возвращает индекс групп. */\nexport function buildTokensResponse(bundle: ParsedBundle, query: TokensQuery): TokensResult {\n const section = bundle.tokens;\n\n if (query.group !== undefined) {\n return section === null ? { ok: false, text: LEGACY_NOTE } : byGroup(section, query.group);\n }\n\n if (query.component !== undefined) {\n return byComponent(bundle, section, query.component);\n }\n\n if (section === null) {\n return {\n ok: true,\n payload: {\n note: LEGACY_NOTE,\n components: bundle.components\n .filter((c) => c.tokens.length > 0)\n .map((c) => ({ component: c.name, tokens: c.tokens })),\n },\n };\n }\n\n return {\n ok: true,\n payload: {\n triplexVersion: bundle.triplexVersion,\n overridePath: section.overridePath,\n core: {\n description: 'Палитра и примитивы. Ссылки { ref: \"ColorBrand.50\" } резолвятся сюда.',\n groups: groupIndex(section, \"core\"),\n },\n components: { groups: groupIndex(section, \"component\") },\n hint: 'Полные данные: get_tokens({ component: \"Calendar\" }) или get_tokens({ group: \"ColorBrand\" }).',\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sberbusiness/triplex-next-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.48.0-beta",
|
|
4
4
|
"description": "MCP-сервер для дизайн-системы Triplex. Предоставляет AI-агентам документацию компонентов, дизайн-токены и примеры использования.",
|
|
5
5
|
"author": "СберБизнес",
|
|
6
6
|
"license": "MIT",
|