@agent-native/core 0.138.0 → 0.140.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +2 -0
- package/corpus/templates/analytics/server/lib/emails.ts +51 -0
- package/corpus/templates/analytics/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/calendar/server/lib/booking-emails.ts +154 -70
- package/corpus/templates/calendar/server/lib/emails.ts +167 -0
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +64 -28
- package/corpus/templates/calendar/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/clips/actions/invite-member.ts +39 -15
- package/corpus/templates/clips/server/lib/emails.ts +256 -0
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +24 -0
- package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +5 -0
- package/corpus/templates/content/server/lib/comment-notifications.ts +57 -26
- package/corpus/templates/content/server/lib/emails.ts +70 -0
- package/corpus/templates/content/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +44 -1
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +265 -1
- package/corpus/templates/design/actions/create-design-system.ts +9 -10
- package/corpus/templates/design/actions/get-design-system.ts +53 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +5 -71
- package/corpus/templates/design/actions/index-design-tokens.ts +61 -80
- package/corpus/templates/design/actions/update-design-system.ts +7 -10
- package/corpus/templates/design/app/components/design/EditPanel.tsx +45 -2
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +12 -0
- package/corpus/templates/design/app/components/design/edit-panel/design-system-swatches.ts +215 -0
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +10 -6
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +19 -3
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +36 -10
- package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +15 -0
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +19 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +6 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +53 -10
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +142 -4
- package/corpus/templates/design/app/components/design/types.ts +6 -0
- package/corpus/templates/design/app/i18n-data.ts +20 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +1 -1
- package/corpus/templates/design/app/pages/DesignSystems.tsx +78 -1
- package/corpus/templates/design/app/pages/design-editor/html-layer-positioning.ts +6 -1
- package/corpus/templates/design/changelog/2026-08-04-design-system-tokens-show-by-name-in-the-editor.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +17 -0
- package/corpus/templates/design/server/lib/design-system-tokens.ts +35 -0
- package/corpus/templates/design/shared/authored-color-styles.ts +401 -0
- package/corpus/templates/design/shared/resolve-tweaks.ts +10 -18
- package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/transactional-email.tsx +4 -0
- package/corpus/templates/forms/server/lib/emails.ts +52 -0
- package/corpus/templates/forms/server/lib/response-email.ts +2 -0
- package/corpus/templates/forms/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/plan/actions/request-plan-access.ts +33 -12
- package/corpus/templates/plan/server/lib/comment-notifications.ts +53 -27
- package/corpus/templates/plan/server/lib/emails.ts +67 -0
- package/corpus/templates/plan/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/slides/server/lib/comment-notifications.ts +44 -21
- package/corpus/templates/slides/server/lib/emails.ts +40 -0
- package/corpus/templates/slides/server/plugins/transactional-emails.ts +5 -0
- package/dist/brand-kit/index.d.ts +1 -0
- package/dist/brand-kit/index.js +1 -0
- package/dist/brand-kit/tokens.d.ts +92 -0
- package/dist/brand-kit/tokens.js +280 -0
- package/dist/brand-kit/types.d.ts +25 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +2 -2
- package/dist/email-catalog/actions/list-email-activity.d.ts +6 -0
- package/dist/email-catalog/actions/list-email-activity.js +15 -0
- package/dist/email-catalog/actions/list-email-engagement.d.ts +6 -0
- package/dist/email-catalog/actions/list-email-engagement.js +15 -0
- package/dist/email-catalog/actions/list-email-log.d.ts +8 -0
- package/dist/email-catalog/actions/list-email-log.js +22 -0
- package/dist/email-catalog/actions/list-transactional-emails.d.ts +23 -0
- package/dist/email-catalog/actions/list-transactional-emails.js +61 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +10 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.js +24 -0
- package/dist/email-catalog/authorize.d.ts +2 -0
- package/dist/email-catalog/authorize.js +10 -0
- package/dist/email-catalog/log.d.ts +57 -0
- package/dist/email-catalog/log.js +117 -0
- package/dist/email-catalog/provider-metrics.d.ts +34 -0
- package/dist/email-catalog/provider-metrics.js +165 -0
- package/dist/email-catalog/registry.d.ts +79 -0
- package/dist/email-catalog/registry.js +71 -0
- package/dist/email-catalog/schema.d.ts +212 -0
- package/dist/email-catalog/schema.js +49 -0
- package/dist/email-catalog/system-emails.d.ts +14 -0
- package/dist/email-catalog/system-emails.js +68 -0
- package/dist/localization/default-messages.d.ts +45 -0
- package/dist/localization/default-messages.js +45 -0
- package/dist/notifications/routes.d.ts +6 -6
- package/dist/org/handlers.js +8 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-discovery.js +22 -0
- package/dist/server/better-auth-instance.js +17 -2
- package/dist/server/email.d.ts +9 -0
- package/dist/server/email.js +44 -3
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/package.json +3 -1
|
@@ -388,6 +388,263 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
388
388
|
};
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
+
// shared/authored-color-styles.ts
|
|
392
|
+
var AUTHORED_COLOR_PROPERTIES = [
|
|
393
|
+
"color",
|
|
394
|
+
"backgroundColor",
|
|
395
|
+
"borderColor",
|
|
396
|
+
"outlineColor",
|
|
397
|
+
// Not colours themselves, but the only place a shadow's colour keeps its name.
|
|
398
|
+
"boxShadow",
|
|
399
|
+
"textShadow"
|
|
400
|
+
];
|
|
401
|
+
var SHORTHAND_FALLBACK = {
|
|
402
|
+
backgroundColor: "background",
|
|
403
|
+
borderColor: "border",
|
|
404
|
+
outlineColor: "outline"
|
|
405
|
+
};
|
|
406
|
+
var INHERITED_PROPERTIES = ["color"];
|
|
407
|
+
var RESET_KEYWORDS = /* @__PURE__ */ new Set([
|
|
408
|
+
"initial",
|
|
409
|
+
"inherit",
|
|
410
|
+
"unset",
|
|
411
|
+
"revert",
|
|
412
|
+
"revert-layer"
|
|
413
|
+
]);
|
|
414
|
+
function isAuthoredColor(value) {
|
|
415
|
+
return typeof value === "string" && value !== "" && !RESET_KEYWORDS.has(value.trim().toLowerCase());
|
|
416
|
+
}
|
|
417
|
+
var LINE_STYLE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
418
|
+
"none",
|
|
419
|
+
"hidden",
|
|
420
|
+
"solid",
|
|
421
|
+
"dashed",
|
|
422
|
+
"dotted",
|
|
423
|
+
"double",
|
|
424
|
+
"groove",
|
|
425
|
+
"ridge",
|
|
426
|
+
"inset",
|
|
427
|
+
"outset"
|
|
428
|
+
]);
|
|
429
|
+
var LINE_WIDTH = /^(thin|medium|thick|-?\\d*\\.?\\d+[a-z%]*)$/i;
|
|
430
|
+
function splitTopLevel(value) {
|
|
431
|
+
const parts = [];
|
|
432
|
+
let depth = 0;
|
|
433
|
+
let current = "";
|
|
434
|
+
for (const char of value) {
|
|
435
|
+
if (char === "(") depth += 1;
|
|
436
|
+
else if (char === ")") depth -= 1;
|
|
437
|
+
if (depth === 0 && /\\s/.test(char)) {
|
|
438
|
+
if (current) parts.push(current);
|
|
439
|
+
current = "";
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
current += char;
|
|
443
|
+
}
|
|
444
|
+
if (current) parts.push(current);
|
|
445
|
+
return parts;
|
|
446
|
+
}
|
|
447
|
+
function lineShorthandColor(value) {
|
|
448
|
+
const rest = splitTopLevel(value).filter((part) => {
|
|
449
|
+
const lower = part.toLowerCase();
|
|
450
|
+
return !LINE_STYLE_KEYWORDS.has(lower) && !LINE_WIDTH.test(part);
|
|
451
|
+
});
|
|
452
|
+
return rest.length === 1 ? rest[0] : null;
|
|
453
|
+
}
|
|
454
|
+
function shorthandColorValue(shorthand, value) {
|
|
455
|
+
const trimmed = value.trim();
|
|
456
|
+
if (!trimmed) return null;
|
|
457
|
+
if (/url\\(|gradient\\(/i.test(trimmed)) return null;
|
|
458
|
+
if (/^var\\(.*\\)$/.test(trimmed)) return trimmed;
|
|
459
|
+
if (shorthand === "border" || shorthand === "outline") {
|
|
460
|
+
return lineShorthandColor(trimmed);
|
|
461
|
+
}
|
|
462
|
+
return /\\s/.test(trimmed) ? null : trimmed;
|
|
463
|
+
}
|
|
464
|
+
function selectorSpecificity(selector) {
|
|
465
|
+
const cleaned = selector.replace(/\\\\./g, "").replace(/\\[[^\\]]*\\]/g, " :attr ").replace(/\\(([^()]*)\\)/g, " ");
|
|
466
|
+
const count = (pattern) => (cleaned.match(pattern) ?? []).length;
|
|
467
|
+
const ids = count(/#[\\w-]+/g);
|
|
468
|
+
const classes = count(/\\.[\\w-]+/g) + count(/:(?!:)[\\w-]+/g);
|
|
469
|
+
const types = count(/(?:^|[\\s>+~])[a-zA-Z][\\w-]*/g) + count(/::[\\w-]+/g);
|
|
470
|
+
return ids * 1e4 + classes * 100 + types;
|
|
471
|
+
}
|
|
472
|
+
function matchedSpecificity(element, selectorText) {
|
|
473
|
+
let best = -1;
|
|
474
|
+
for (const selector of selectorText.split(",")) {
|
|
475
|
+
const trimmed = selector.trim();
|
|
476
|
+
if (!trimmed) continue;
|
|
477
|
+
try {
|
|
478
|
+
if (!element.matches(trimmed)) continue;
|
|
479
|
+
} catch {
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
best = Math.max(best, selectorSpecificity(trimmed));
|
|
483
|
+
}
|
|
484
|
+
return best;
|
|
485
|
+
}
|
|
486
|
+
var INLINE_SPECIFICITY = Number.MAX_SAFE_INTEGER;
|
|
487
|
+
function beats(next, current) {
|
|
488
|
+
if (!current) return true;
|
|
489
|
+
if (next.important !== current.important) return next.important;
|
|
490
|
+
if (next.specificity !== current.specificity) {
|
|
491
|
+
return next.specificity > current.specificity;
|
|
492
|
+
}
|
|
493
|
+
return next.order >= current.order;
|
|
494
|
+
}
|
|
495
|
+
function readRules(element, rules, out, counter) {
|
|
496
|
+
if (!rules) return;
|
|
497
|
+
for (let index = 0; index < rules.length; index += 1) {
|
|
498
|
+
const rule = rules[index];
|
|
499
|
+
if (!rule) continue;
|
|
500
|
+
const declaresOwnStyles = Boolean(rule.selectorText && rule.style);
|
|
501
|
+
if (!declaresOwnStyles) {
|
|
502
|
+
if (!rule.cssRules) continue;
|
|
503
|
+
if (rule.conditionText === void 0) {
|
|
504
|
+
readRules(element, rule.cssRules, out, counter);
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
let applies = false;
|
|
508
|
+
try {
|
|
509
|
+
applies = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(rule.conditionText).matches : false;
|
|
510
|
+
} catch {
|
|
511
|
+
applies = false;
|
|
512
|
+
}
|
|
513
|
+
if (applies) readRules(element, rule.cssRules, out, counter);
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
if (rule.cssRules?.length) {
|
|
517
|
+
readRules(element, rule.cssRules, out, counter);
|
|
518
|
+
}
|
|
519
|
+
if (!rule.selectorText || !rule.style) continue;
|
|
520
|
+
const specificity = matchedSpecificity(element, rule.selectorText);
|
|
521
|
+
if (specificity < 0) continue;
|
|
522
|
+
const order = counter.order++;
|
|
523
|
+
const style = rule.style;
|
|
524
|
+
const priority = (name) => style.getPropertyPriority?.(name) === "important";
|
|
525
|
+
const offer = (property, value, cssName) => {
|
|
526
|
+
const candidate = {
|
|
527
|
+
value,
|
|
528
|
+
important: priority(cssName),
|
|
529
|
+
specificity,
|
|
530
|
+
order
|
|
531
|
+
};
|
|
532
|
+
if (beats(candidate, out[property])) out[property] = candidate;
|
|
533
|
+
};
|
|
534
|
+
for (const property of AUTHORED_COLOR_PROPERTIES) {
|
|
535
|
+
const declared = style[property];
|
|
536
|
+
if (isAuthoredColor(declared)) {
|
|
537
|
+
offer(property, declared, cssPropertyName(property));
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
const shorthand = SHORTHAND_FALLBACK[property];
|
|
541
|
+
if (!shorthand) continue;
|
|
542
|
+
const shorthandValue = style[shorthand];
|
|
543
|
+
if (typeof shorthandValue !== "string") continue;
|
|
544
|
+
const colorOnly = shorthandColorValue(shorthand, shorthandValue);
|
|
545
|
+
if (colorOnly) offer(property, colorOnly, shorthand);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
function cssPropertyName(property) {
|
|
550
|
+
return property.replace(/[A-Z]/g, (c) => \`-\${c.toLowerCase()}\`);
|
|
551
|
+
}
|
|
552
|
+
function authoredMatchesPainted(element, property, authored) {
|
|
553
|
+
const view = element.ownerDocument?.defaultView;
|
|
554
|
+
if (!view || typeof view.getComputedStyle !== "function") return true;
|
|
555
|
+
let painted = "";
|
|
556
|
+
try {
|
|
557
|
+
painted = view.getComputedStyle(element)[property] ?? "";
|
|
558
|
+
} catch {
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
if (!painted) return true;
|
|
562
|
+
const probe = element.ownerDocument.createElement("span");
|
|
563
|
+
const name = cssPropertyName(property);
|
|
564
|
+
probe.style.setProperty("display", "none");
|
|
565
|
+
probe.style.setProperty(name, authored);
|
|
566
|
+
if (!probe.style.getPropertyValue(name)) return false;
|
|
567
|
+
element.appendChild(probe);
|
|
568
|
+
let resolved = "";
|
|
569
|
+
try {
|
|
570
|
+
resolved = view.getComputedStyle(probe)[property] ?? "";
|
|
571
|
+
} catch {
|
|
572
|
+
resolved = "";
|
|
573
|
+
}
|
|
574
|
+
probe.remove();
|
|
575
|
+
return resolved === "" || resolved === painted;
|
|
576
|
+
}
|
|
577
|
+
function collectForElement(element) {
|
|
578
|
+
const ranked = {};
|
|
579
|
+
const counter = { order: 0 };
|
|
580
|
+
try {
|
|
581
|
+
const doc = element.ownerDocument;
|
|
582
|
+
const sheets = [
|
|
583
|
+
...Array.from(doc?.styleSheets ?? []),
|
|
584
|
+
...Array.from(
|
|
585
|
+
doc?.adoptedStyleSheets ?? []
|
|
586
|
+
)
|
|
587
|
+
];
|
|
588
|
+
for (const sheet of sheets) {
|
|
589
|
+
let rules;
|
|
590
|
+
try {
|
|
591
|
+
rules = sheet.cssRules;
|
|
592
|
+
} catch {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
readRules(element, rules, ranked, counter);
|
|
596
|
+
}
|
|
597
|
+
} catch (error) {
|
|
598
|
+
console.warn(
|
|
599
|
+
"[design] could not read stylesheets for authored colours; token names will fall back to resolved values",
|
|
600
|
+
error
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
const inline = element.style;
|
|
604
|
+
if (inline) {
|
|
605
|
+
const order = counter.order++;
|
|
606
|
+
for (const property of AUTHORED_COLOR_PROPERTIES) {
|
|
607
|
+
const value = inline[property];
|
|
608
|
+
if (!isAuthoredColor(value)) continue;
|
|
609
|
+
const candidate = {
|
|
610
|
+
value,
|
|
611
|
+
important: inline.getPropertyPriority?.(cssPropertyName(property)) === "important",
|
|
612
|
+
specificity: INLINE_SPECIFICITY,
|
|
613
|
+
order
|
|
614
|
+
};
|
|
615
|
+
if (beats(candidate, ranked[property])) ranked[property] = candidate;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
const out = {};
|
|
619
|
+
for (const [property, candidate] of Object.entries(ranked)) {
|
|
620
|
+
out[property] = candidate.value;
|
|
621
|
+
}
|
|
622
|
+
return out;
|
|
623
|
+
}
|
|
624
|
+
function collectAuthoredColorStyles(element) {
|
|
625
|
+
const out = collectForElement(element);
|
|
626
|
+
for (const property of Object.keys(out)) {
|
|
627
|
+
if (!authoredMatchesPainted(element, property, out[property])) {
|
|
628
|
+
delete out[property];
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
for (const property of INHERITED_PROPERTIES) {
|
|
632
|
+
if (out[property]) continue;
|
|
633
|
+
let ancestor = element.parentElement;
|
|
634
|
+
while (ancestor) {
|
|
635
|
+
const inherited = collectForElement(ancestor)[property];
|
|
636
|
+
if (inherited) {
|
|
637
|
+
if (authoredMatchesPainted(element, property, inherited)) {
|
|
638
|
+
out[property] = inherited;
|
|
639
|
+
}
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
ancestor = ancestor.parentElement;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return out;
|
|
646
|
+
}
|
|
647
|
+
|
|
391
648
|
// app/components/design/bridge/editor-chrome.bridge.ts
|
|
392
649
|
(function() {
|
|
393
650
|
if (window.__anEditorChromeBridge) return;
|
|
@@ -1633,7 +1890,13 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
1633
1890
|
"width",
|
|
1634
1891
|
"height",
|
|
1635
1892
|
"transform",
|
|
1636
|
-
"whiteSpace"
|
|
1893
|
+
"whiteSpace",
|
|
1894
|
+
"color",
|
|
1895
|
+
"backgroundColor",
|
|
1896
|
+
"borderColor",
|
|
1897
|
+
"outlineColor",
|
|
1898
|
+
"boxShadow",
|
|
1899
|
+
"textShadow"
|
|
1637
1900
|
];
|
|
1638
1901
|
function collectInlineStyles(el) {
|
|
1639
1902
|
var styles = {};
|
|
@@ -1837,6 +2100,7 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
1837
2100
|
whiteSpace: cs.whiteSpace
|
|
1838
2101
|
},
|
|
1839
2102
|
inlineStyles: collectInlineStyles(el),
|
|
2103
|
+
authoredColorStyles: collectAuthoredColorStyles(el),
|
|
1840
2104
|
primitiveKind: el.getAttribute("data-an-primitive") || void 0,
|
|
1841
2105
|
portableStyleSnapshot: collectPortableStyleSnapshot(el),
|
|
1842
2106
|
boundingRect: {
|
|
@@ -8,6 +8,7 @@ import { nanoid } from "nanoid";
|
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
|
|
10
10
|
import { getDb, schema } from "../server/db/index.js";
|
|
11
|
+
import { assertStorableDesignSystemTokens } from "../server/lib/design-system-tokens.js";
|
|
11
12
|
import {
|
|
12
13
|
DESIGN_SYSTEM_TEMPLATE_IDS,
|
|
13
14
|
getProductionDesignSystemTemplate,
|
|
@@ -39,7 +40,13 @@ export const createDesignSystemSchema = z
|
|
|
39
40
|
.min(1, "data is required")
|
|
40
41
|
.optional()
|
|
41
42
|
.describe(
|
|
42
|
-
"JSON string of DesignSystemData (required without templateId; templates supply their verified token snapshot)"
|
|
43
|
+
"JSON string of DesignSystemData (required without templateId; templates supply their verified token snapshot). " +
|
|
44
|
+
"Include a `tokens` array whenever the source names its tokens: " +
|
|
45
|
+
// guard:allow-raw-color — an agent-facing payload example, not a styled value
|
|
46
|
+
'[{ "name": "interactive-01", "cssVar": "--cds-interactive-01", "value": "#0F62FE", ' +
|
|
47
|
+
'"type": "color", "group": "Colors/Interactive", "source": "Carbon v11" }]. ' +
|
|
48
|
+
"The seven `colors` roles are a summary for generation, not a place to squash a " +
|
|
49
|
+
"real system's vocabulary into — send both.",
|
|
43
50
|
),
|
|
44
51
|
assets: z
|
|
45
52
|
.string()
|
|
@@ -111,15 +118,7 @@ export default defineAction({
|
|
|
111
118
|
throw new Error("title and data are required");
|
|
112
119
|
}
|
|
113
120
|
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
const parsed = JSON.parse(resolvedData);
|
|
117
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
118
|
-
throw new Error();
|
|
119
|
-
}
|
|
120
|
-
} catch {
|
|
121
|
-
throw new Error("data must be a valid JSON object string");
|
|
122
|
-
}
|
|
121
|
+
assertStorableDesignSystemTokens(resolvedData);
|
|
123
122
|
if (assets) {
|
|
124
123
|
try {
|
|
125
124
|
JSON.parse(assets);
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import {
|
|
3
|
+
brandKitRoleTokens,
|
|
4
|
+
resolveBrandKitTokens,
|
|
5
|
+
} from "@agent-native/core/brand-kit/tokens";
|
|
2
6
|
import {
|
|
3
7
|
hydrateBuilderDesignSystemReference,
|
|
4
8
|
parseBuilderDesignSystemProxyReference,
|
|
@@ -61,6 +65,54 @@ function formatTokenValues(tokenValues: Record<string, string>): string[] {
|
|
|
61
65
|
];
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
const MAX_LISTED_TOKENS = 40;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Require generated CSS to reference tokens rather than paste their values. A
|
|
72
|
+
* colour cannot identify a token afterwards — Carbon points four at one blue.
|
|
73
|
+
*/
|
|
74
|
+
function tokenReferenceDirective(data: unknown): string[] {
|
|
75
|
+
if (!data || typeof data !== "object") return [];
|
|
76
|
+
const kit = data as {
|
|
77
|
+
tokens?: unknown;
|
|
78
|
+
customCSS?: unknown;
|
|
79
|
+
colors?: object | null;
|
|
80
|
+
borders?: { radius?: string } | null;
|
|
81
|
+
spacing?: object | null;
|
|
82
|
+
};
|
|
83
|
+
const tokens = [
|
|
84
|
+
...resolveBrandKitTokens(kit),
|
|
85
|
+
...brandKitRoleTokens(kit),
|
|
86
|
+
].filter((token) => token.type === "color");
|
|
87
|
+
if (tokens.length === 0) return [];
|
|
88
|
+
|
|
89
|
+
const seen = new Set<string>();
|
|
90
|
+
const listed: string[] = [];
|
|
91
|
+
for (const token of tokens) {
|
|
92
|
+
if (seen.has(token.cssVar)) continue;
|
|
93
|
+
seen.add(token.cssVar);
|
|
94
|
+
listed.push(`- ${token.cssVar}: ${token.value}`);
|
|
95
|
+
if (listed.length >= MAX_LISTED_TOKENS) break;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return [
|
|
99
|
+
"",
|
|
100
|
+
"### Reference these color tokens, do not paste their values",
|
|
101
|
+
"Write the token reference with its value as a fallback:",
|
|
102
|
+
// guard:allow-raw-color — the do/don't example shown to the generating agent
|
|
103
|
+
" background: var(--color-accent, #0f62fe); /* yes */",
|
|
104
|
+
// guard:allow-raw-color — the counter-example it must not copy
|
|
105
|
+
" background: #0f62fe; /* no */",
|
|
106
|
+
"The fallback is required — exports and unlinked designs define no custom",
|
|
107
|
+
"properties, and a bare var() renders transparent there. Define every token",
|
|
108
|
+
"you reference in the screen's `:root` block too.",
|
|
109
|
+
...listed,
|
|
110
|
+
seen.size > MAX_LISTED_TOKENS
|
|
111
|
+
? `- …and ${seen.size - MAX_LISTED_TOKENS} more; call get-design-system for the full set.`
|
|
112
|
+
: "",
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
|
|
64
116
|
function buildDesignSystemAgentContext({
|
|
65
117
|
id,
|
|
66
118
|
title,
|
|
@@ -82,6 +134,7 @@ function buildDesignSystemAgentContext({
|
|
|
82
134
|
"## Selected Design System Context",
|
|
83
135
|
`Use "${title}" (id: ${id}) as the visual source of truth for this generation.`,
|
|
84
136
|
"Apply these tokens, assets, and usage notes before choosing colors, type, spacing, radius, imagery, or component language.",
|
|
137
|
+
...tokenReferenceDirective(parseJson(data)),
|
|
85
138
|
];
|
|
86
139
|
|
|
87
140
|
if (description?.trim()) {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import {
|
|
3
|
+
classifyBrandKitToken as classifyVar,
|
|
4
|
+
friendlyTokenName as friendlyName,
|
|
5
|
+
isColorTokenValue as isColorValue,
|
|
6
|
+
} from "@agent-native/core/brand-kit/tokens";
|
|
2
7
|
import { buildDeepLink } from "@agent-native/core/server";
|
|
3
8
|
import {
|
|
4
9
|
CODE_MAX_FILES,
|
|
@@ -116,70 +121,6 @@ function designDeepLink(designId: string): string {
|
|
|
116
121
|
});
|
|
117
122
|
}
|
|
118
123
|
|
|
119
|
-
function classifyVar(name: string, value: string): ImportedTokenType {
|
|
120
|
-
const n = name.toLowerCase();
|
|
121
|
-
if (
|
|
122
|
-
/color|bg|background|text|border|accent|primary|secondary|surface|muted|foreground|fill|stroke/i.test(
|
|
123
|
-
n,
|
|
124
|
-
) ||
|
|
125
|
-
isColorValue(value)
|
|
126
|
-
) {
|
|
127
|
-
return "color";
|
|
128
|
-
}
|
|
129
|
-
if (/font|size|leading|tracking|weight|heading|body|type/i.test(n)) {
|
|
130
|
-
return "typography";
|
|
131
|
-
}
|
|
132
|
-
if (/radius|rounded/i.test(n)) return "radius";
|
|
133
|
-
if (/spacing|gap|padding|margin|space/i.test(n)) return "spacing";
|
|
134
|
-
if (/shadow|blur|drop/i.test(n)) return "shadow";
|
|
135
|
-
return "other";
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function isColorValue(value: string): boolean {
|
|
139
|
-
const normalized = value.trim().toLowerCase();
|
|
140
|
-
if (
|
|
141
|
-
/^(#[0-9a-fA-F]{3,8}|rgba?\(|hsla?\(|oklch\(|color\()/i.test(normalized)
|
|
142
|
-
) {
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
return [
|
|
146
|
-
"red",
|
|
147
|
-
"blue",
|
|
148
|
-
"green",
|
|
149
|
-
"yellow",
|
|
150
|
-
"orange",
|
|
151
|
-
"purple",
|
|
152
|
-
"pink",
|
|
153
|
-
"cyan",
|
|
154
|
-
"magenta",
|
|
155
|
-
"teal",
|
|
156
|
-
"navy",
|
|
157
|
-
"maroon",
|
|
158
|
-
"coral",
|
|
159
|
-
"salmon",
|
|
160
|
-
"gold",
|
|
161
|
-
"silver",
|
|
162
|
-
"gray",
|
|
163
|
-
"grey",
|
|
164
|
-
"indigo",
|
|
165
|
-
"violet",
|
|
166
|
-
"lime",
|
|
167
|
-
"olive",
|
|
168
|
-
"aqua",
|
|
169
|
-
"fuchsia",
|
|
170
|
-
"crimson",
|
|
171
|
-
"turquoise",
|
|
172
|
-
"ivory",
|
|
173
|
-
"beige",
|
|
174
|
-
"lavender",
|
|
175
|
-
"tan",
|
|
176
|
-
"khaki",
|
|
177
|
-
"plum",
|
|
178
|
-
"orchid",
|
|
179
|
-
"sienna",
|
|
180
|
-
].includes(normalized);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
124
|
function toKebab(value: string): string {
|
|
184
125
|
return (
|
|
185
126
|
value
|
|
@@ -193,13 +134,6 @@ function toKebab(value: string): string {
|
|
|
193
134
|
);
|
|
194
135
|
}
|
|
195
136
|
|
|
196
|
-
function friendlyName(cssVar: string): string {
|
|
197
|
-
return cssVar
|
|
198
|
-
.replace(/^--/, "")
|
|
199
|
-
.replace(/[-_]/g, " ")
|
|
200
|
-
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
201
|
-
}
|
|
202
|
-
|
|
203
137
|
function normalizeValue(value: string): string {
|
|
204
138
|
return value
|
|
205
139
|
.trim()
|