@ikas/code-components-mcp 1.4.0-beta.63 → 1.4.0-beta.64

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.
@@ -549,7 +549,7 @@
549
549
  "theme-globals": {
550
550
  "title": "Theme Global Settings & Design Tokens",
551
551
  "description": "Read and create the theme's global variables and design tokens (colors, typography, breakpoints, keyframes, color schemes) from code components",
552
- "content": "The theme developer defines global settings in the editor's \"Styles\" panel. Code components can READ these at runtime and an AI agent can CREATE/LIST them via MCP tools. Prefer reusing the theme's existing tokens (colors, typography) over hardcoding values — it keeps components consistent with the store's design.\n\n### Read at runtime (in your .tsx)\n\nImport from `@ikas/bp-storefront`. These work in SSR, client hydration, and the editor canvas:\n\n```tsx\nimport {\n getThemeSetting, getThemeSettings, // global variables (Theme Settings)\n getThemeColors, getThemeTypography, // design tokens\n getThemeBreakpoints, getThemeKeyframes, getThemeColorSchemes,\n} from \"@ikas/bp-storefront\";\n\nconst brand = getThemeSetting(\"_AbC123XyZ\")?.value; // key = variableName, from list_theme_globals\nconst colors = getThemeColors(); // [{ id, name, resolved, cssVar }]\n// resolved = concrete value (e.g. \"#ff0000\"); cssVar = \"var(--<id>)\" (scheme-aware).\n// e.g. style={{ color: colors[0].cssVar }} or className={getThemeTypography()[0].className}\n```\n\nShapes: colors → `{ id, name, resolved, cssVar }`; typography → `{ id, name, resolved, className }`; breakpoints → `{ id, name, width }`; keyframes → `{ id, name, type, ref }`; color schemes → `{ schemes, values }`. Global variables → `{ name, displayName, type, value }` where `name` is the stable runtime key (`variableName`).\n\n### Using a color scheme\n\nColor schemes have two parts: **slots** (the named color keys, e.g. Background/Text/Primary) and **palettes** (sets of colors for those slots). `getThemeColorSchemes()` returns:\n- `schemes`: the slots — `[{ id, name }]`.\n- `values`: the palettes — `[{ id, name, isDefault, className, colorsByScheme }]`, where `colorsByScheme` maps each **slot id** → `{ resolved, cssVar }`.\n\nA scheme color's `cssVar` is `var(--<slotId>)` and is **palette-scoped**: it only resolves inside an element carrying that palette's `className`. So apply the palette to a wrapper, then reference its slots inside:\n\n```tsx\nconst { schemes, values } = getThemeColorSchemes();\nconst palette = values.find((v) => v.isDefault) ?? values[0];\nconst slot = (name: string) => {\n const s = schemes.find((x) => x.name === name);\n return s ? palette?.colorsByScheme[s.id] : undefined;\n};\n\n// the palette className makes the slot vars resolve in this subtree\nreturn (\n <section\n className={palette?.className}\n style={{ background: slot(\"Background\")?.cssVar, color: slot(\"Text\")?.cssVar }}\n >\n <button style={{ background: slot(\"Primary\")?.cssVar }}>Buy</button>\n </section>\n);\n```\n\nUse `colorsByScheme[slotId].resolved` if you need the concrete value instead of the live `var()`. Switching palettes at runtime is just swapping the wrapper's `className`.\n\n### Forcing a palette vs. inheriting the section's scheme\n\nSlot vars (`var(--<slotId>)`) resolve against whichever palette `className` sits on an **ancestor**, so you get two modes:\n\n- **Inherit the section's scheme (default, recommended):** do NOT add a palette `className` — just use the slot `cssVar`s. They resolve to the palette the section is set to. A section's color scheme is chosen in the editor (right panel → \"Color Scheme\"), which renders the section wrapper with that palette's class (`_<schemeId>`); leaving your slots unwrapped lets the merchant re-skin the component by switching the section's scheme, with no code change. The var NAMES are identical across palettes (only the value changes with the active ancestor class), so read the `{slotId → cssVar}` map from any palette and stay unwrapped:\n\n```tsx\nconst { schemes, values } = getThemeColorSchemes();\nconst palette = values.find((v) => v.isDefault) ?? values[0]; // any palette; var names match across all\nconst slot = (name: string) => {\n const s = schemes.find((x) => x.name === name);\n return s ? palette?.colorsByScheme[s.id]?.cssVar : undefined;\n};\n\n// No palette className here → these inherit the SECTION's active scheme.\nreturn (\n <div style={{ background: slot(\"Background\"), color: slot(\"Text\") }}>\n <button style={{ background: slot(\"Primary\") }}>Buy</button>\n </div>\n);\n```\n\n- **Force a specific palette:** wrap the subtree in that palette's `className` (the example above). Use this only for a region that must always use one fixed palette regardless of the section's scheme.\n\n### Create / list via MCP (requires `ikas-component dev` + connected editor)\n\n- `list_theme_globals` — list every global variable and design token in the project (including ones created manually in the editor). **Call this FIRST** so you reuse existing tokens instead of duplicating them.\n- `create_theme_global` — create one, selected by `kind`:\n - `globalVariable` — `display_name` + `type` (TEXT|RICH_TEXT|IMAGE|COLOR|NUMBER|BOOLEAN|BORDER|SHADOW); `value` optional. Value shapes — TEXT/COLOR: string; RICH_TEXT: HTML string; NUMBER: number; BOOLEAN: boolean; IMAGE: `{ url }`; BORDER: `{ width: { value, unit }, style, color }`; SHADOW: `{ x, y, blur, spread, color, position: \"outside\"|\"inside\" }`.\n - `color` — `name` + `value` (hex).\n - `typography` — `name` + any of `font_family`/`font_size`/`font_weight`/`line_height`/`letter_spacing`.\n - `breakpoint` — `name` + `width`.\n - `keyframe` — `name` + `points` (`[{ point, styles? }]`); each style is `{ property, value }` with a CSS property name (opacity, transform, filter, background, color, …). Apply the keyframe's `ref` as a CSS `animation-name` and set timing (duration/iteration) where you apply it.\n - `colorScheme` — `name` + `colors` (`[{ key, value }]`); `key` is a color slot name (e.g. Background, Text, Primary) and slots are created automatically if missing.\n\n**CLI equivalents** (if you call the ikas-component CLI directly instead of the MCP tools): read with `list-theme-globals`; create with — globalVariable→`create-global-variable`, color→`create-color`, typography→`create-text-style`, breakpoint→`create-breakpoint`, keyframe→`create-keyframe`, colorScheme→`create-color-scheme`. CLI flags are kebab-case (`--display-name`, `--font-size`, `--colors`, …) and the CLI must be run from the project root.\n\n**Update / delete:** `update_theme_global` (fix a global variable's value/type — identify by `name`) and `delete_theme_global` (`kind` globalVariable→`name`, or a design-token kind→`id`). CLI equivalents: `update-global-variable`, `delete-global-variable`, `delete-design-token`.\n\nAfter creating, the new item is readable via the runtime getters above (its key/id comes back in the create result and from `list_theme_globals`).\n\n### Live updates vs snapshots (important)\n\nTheme settings reach your component through two channels — pick the right one or edits won't reflect live:\n\n- **Live (CSS):** use `cssVar` (colors, and color-scheme colors) and `className` (typography text styles). These update **instantly** when the value is edited in the editor, because they map to CSS the editor regenerates live. Prefer these for anything visual.\n - Colors: `style={{ color: token.cssVar }}` (or `background`).\n - Typography: apply the text style's class — `className={t.className}` — do NOT spread `t.resolved` into an inline `style` if you want live updates.\n - Color-scheme colors are scoped to the palette: a `var(--<key>)` only resolves inside an element carrying that palette's `className`, so wrap the row: `<div className={paletteValue.className}>…<span style={{background: colorsByScheme[keyId].cssVar}}/>…</div>`.\n- **Snapshot (JS):** `resolved` values, breakpoint `width`, keyframe metadata, and global-variable `value`s are read from JS at render time. They reflect editor edits only when the component **re-renders/remounts** (e.g. its props change, or another action refreshes the canvas) — NOT instantly on a theme-token edit. This is expected, not a bug. Global-variable value edits do trigger a canvas refresh, so they reflect; design-token `resolved` values lag until the next refresh.\n\nRule of thumb: for visuals that must track editor edits live, reference `cssVar` / apply `className`; treat `resolved` and `value` as point-in-time reads.\n\n### Portability (shipping as a partner design asset)\n\nWhen this component is published as a partner design asset and installed into another store, only the globals it DECLARES as dependencies travel with it. Write components so their global usage stays portable:\n\n- **Expose theme global variables as props — don't hardcode keys.** A prop bound to a global variable (via its `privateVarMap`) is detected and ships with the asset. A `themeValue(\"_xyz\")` / `getThemeSetting(\"_xyz\")` call with a hardcoded key in your source is NOT detected, so that variable won't travel and resolves to nothing in the destination store. If you need a theme setting, add it as a prop and read the prop, not a hardcoded key.\n- **Iterate the runtime lists instead of hardcoding token ids.** `getThemeColors()`, `getThemeTypography()`, `getThemeKeyframes()`, `getThemeBreakpoints()`, and `getThemeColorSchemes()` return the DESTINATION store's own tokens — iterate them so the component adapts to whatever theme it lands in. A specific color/keyframe id hardcoded from the list won't exist in another store.\n- **Travels automatically:** color schemes (in full — the slot/palette pattern above keeps working after install), types referenced by your props, nested code components, and shared modules.\n\nRule of thumb: read named settings through props and read colors/typography/etc. by iterating the runtime lists — both are portable; a hardcoded global id in source is not.",
552
+ "content": "The theme developer defines global settings in the editor's \"Styles\" panel. Code components can READ these at runtime and an AI agent can CREATE/LIST them via MCP tools. Prefer reusing the theme's existing tokens (colors, typography) over hardcoding values — it keeps components consistent with the store's design.\n\n### Read at runtime (in your .tsx)\n\nImport from `@ikas/bp-storefront`. These work in SSR, client hydration, and the editor canvas:\n\n```tsx\nimport {\n getThemeSetting, getThemeSettings, // global variables (Theme Settings)\n getThemeColors, getThemeTypography, // design tokens\n getThemeBreakpoints, getThemeKeyframes, getThemeColorSchemes,\n} from \"@ikas/bp-storefront\";\n\nconst brand = getThemeSetting(\"_AbC123XyZ\")?.value; // key = variableName, from list_theme_globals\nconst colors = getThemeColors(); // [{ id, name, resolved, cssVar }]\n// resolved = concrete value (e.g. \"#ff0000\"); cssVar = \"var(--<id>)\" (scheme-aware).\n// e.g. style={{ color: colors[0].cssVar }} or className={getThemeTypography()[0].className}\n```\n\nShapes: colors → `{ id, name, resolved, cssVar }`; typography → `{ id, name, resolved, className }`; breakpoints → `{ id, name, width }`; keyframes → `{ id, name, type, ref }`; color schemes → `{ schemes, values }`. Global variables → `{ name, displayName, type, value }` where `name` is the stable runtime key (`variableName`).\n\n### Using a color scheme\n\nColor schemes have two parts: **slots** (the named color keys, e.g. Background/Text/Primary) and **palettes** (sets of colors for those slots). `getThemeColorSchemes()` returns:\n- `schemes`: the slots — `[{ id, name }]`.\n- `values`: the palettes — `[{ id, name, isDefault, className, colorsByScheme }]`, where `colorsByScheme` maps each **slot id** → `{ resolved, cssVar }`.\n\nA scheme color's `cssVar` is `var(--<slotId>)` and is **palette-scoped**: it only resolves inside an element carrying that palette's `className`. So apply the palette to a wrapper, then reference its slots inside:\n\n```tsx\nconst { schemes, values } = getThemeColorSchemes();\nconst palette = values.find((v) => v.isDefault) ?? values[0];\nconst slot = (name: string) => {\n const s = schemes.find((x) => x.name === name);\n return s ? palette?.colorsByScheme[s.id] : undefined;\n};\n\n// the palette className makes the slot vars resolve in this subtree\nreturn (\n <section\n className={palette?.className}\n style={{ background: slot(\"Background\")?.cssVar, color: slot(\"Text\")?.cssVar }}\n >\n <button style={{ background: slot(\"Primary\")?.cssVar }}>Buy</button>\n </section>\n);\n```\n\nUse `colorsByScheme[slotId].resolved` if you need the concrete value instead of the live `var()`. Switching palettes at runtime is just swapping the wrapper's `className`.\n\n### Create / list via MCP (requires `ikas-component dev` + connected editor)\n\n- `list_theme_globals` — list every global variable and design token in the project (including ones created manually in the editor). **Call this FIRST** so you reuse existing tokens instead of duplicating them.\n- `create_theme_global` — create one, selected by `kind`:\n - `globalVariable` — `display_name` + `type` (TEXT|RICH_TEXT|IMAGE|COLOR|NUMBER|BOOLEAN|BORDER|SHADOW); `value` optional. Value shapes — TEXT/COLOR: string; RICH_TEXT: HTML string; NUMBER: number; BOOLEAN: boolean; IMAGE: `{ url }`; BORDER: `{ width: { value, unit }, style, color }`; SHADOW: `{ x, y, blur, spread, color, position: \"outside\"|\"inside\" }`.\n - `color` — `name` + `value` (hex).\n - `typography` — `name` + any of `font_family`/`font_size`/`font_weight`/`line_height`/`letter_spacing`.\n - `breakpoint` — `name` + `width`.\n - `keyframe` — `name` + `points` (`[{ point, styles? }]`); each style is `{ property, value }` with a CSS property name (opacity, transform, filter, background, color, …). Apply the keyframe's `ref` as a CSS `animation-name` and set timing (duration/iteration) where you apply it.\n - `colorScheme` — `name` + `colors` (`[{ key, value }]`); `key` is a color slot name (e.g. Background, Text, Primary) and slots are created automatically if missing.\n\n**CLI equivalents** (if you call the ikas-component CLI directly instead of the MCP tools): read with `list-theme-globals`; create with — globalVariable→`create-global-variable`, color→`create-color`, typography→`create-text-style`, breakpoint→`create-breakpoint`, keyframe→`create-keyframe`, colorScheme→`create-color-scheme`. CLI flags are kebab-case (`--display-name`, `--font-size`, `--colors`, …) and the CLI must be run from the project root.\n\n**Update / delete:** `update_theme_global` (fix a global variable's value/type — identify by `name`) and `delete_theme_global` (`kind` globalVariable→`name`, or a design-token kind→`id`). CLI equivalents: `update-global-variable`, `delete-global-variable`, `delete-design-token`.\n\nAfter creating, the new item is readable via the runtime getters above (its key/id comes back in the create result and from `list_theme_globals`).\n\n### Live updates vs snapshots (important)\n\nTheme settings reach your component through two channels — pick the right one or edits won't reflect live:\n\n- **Live (CSS):** use `cssVar` (colors, and color-scheme colors) and `className` (typography text styles). These update **instantly** when the value is edited in the editor, because they map to CSS the editor regenerates live. Prefer these for anything visual.\n - Colors: `style={{ color: token.cssVar }}` (or `background`).\n - Typography: apply the text style's class — `className={t.className}` — do NOT spread `t.resolved` into an inline `style` if you want live updates.\n - Color-scheme colors are scoped to the palette: a `var(--<key>)` only resolves inside an element carrying that palette's `className`, so wrap the row: `<div className={paletteValue.className}>…<span style={{background: colorsByScheme[keyId].cssVar}}/>…</div>`.\n- **Snapshot (JS):** `resolved` values, breakpoint `width`, keyframe metadata, and global-variable `value`s are read from JS at render time. They reflect editor edits only when the component **re-renders/remounts** (e.g. its props change, or another action refreshes the canvas) — NOT instantly on a theme-token edit. This is expected, not a bug. Global-variable value edits do trigger a canvas refresh, so they reflect; design-token `resolved` values lag until the next refresh.\n\nRule of thumb: for visuals that must track editor edits live, reference `cssVar` / apply `className`; treat `resolved` and `value` as point-in-time reads.",
553
553
  "tags": [
554
554
  "theme",
555
555
  "global variables",
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-06-16T21:25:30.203Z",
2
+ "generatedAt": "2026-06-17T08:41:12.163Z",
3
3
  "functions": [
4
4
  {
5
5
  "name": "apiListProductBrand",
@@ -15141,7 +15141,7 @@
15141
15141
  {
15142
15142
  "name": "getThemeSetting",
15143
15143
  "signature": "function getThemeSetting(name: string): ThemeSetting | undefined",
15144
- "description": "A single global variable by its stable key (`variableName`, e.g. `_6Q0KV7VGGM`).\nDiscover keys via (each item carries a human `displayName`).\nThe returned `value` is the live blueprint value when available, else the default.\nIts shape is discriminated by `type` (see ); note an\nIMAGE setting's value is an image REFERENCE (no `.url`) — resolve with\n`getDefaultSrc`/`getSrc`.",
15144
+ "description": "A single global variable by its stable key (`variableName`, e.g. `_6Q0KV7VGGM`).\nDiscover keys via (each item carries a human `displayName`).\nThe returned `value` is the live blueprint value when available, else the default.",
15145
15145
  "params": [],
15146
15146
  "returnType": "ThemeSetting | undefined",
15147
15147
  "categories": [],
@@ -15207,7 +15207,7 @@
15207
15207
  {
15208
15208
  "name": "getThemeColorSchemes",
15209
15209
  "signature": "function getThemeColorSchemes(): { schemes: { id: string; name: string }[]; values: ColorSchemeToken[] }",
15210
- "description": "Theme color schemes (palettes). Returns two PARALLEL lists with different jobs:\n- `schemes`: the color SLOTS as `{ id, name }` LABELS only — no colors live here.\n Use it to resolve a slot's display name from its id.\n- `values`: the actual palettes. A palette's colors live in its `colorsByScheme`\n map, keyed by slot id → `{ resolved, cssVar }`.\n\nTo render swatches, iterate `values[].colorsByScheme` (the source of truth for\ncolors), NOT the top-level `schemes` array — `schemes` carries labels only, so\niterating it renders empty. Look up each swatch's label from `schemes` by its\nslot-id key:\n\n const { schemes, values } = getThemeColorSchemes();\n const slotName = (id: string) => schemes.find(s => s.id === id)?.name ?? id;\n values.forEach(palette =>\n Object.entries(palette.colorsByScheme).forEach(([slotId, { resolved, cssVar }]) => {\n // slotName(slotId) → label, cssVar → live var() ref (prefer this), resolved → hex snapshot\n })\n );",
15210
+ "description": "Theme color schemes — the available schemes plus per-scheme color values.",
15211
15211
  "params": [],
15212
15212
  "returnType": "{ schemes: { id: string; name: string }[]; values: ColorSchemeToken[] }",
15213
15213
  "categories": [],
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-06-16T21:25:30.240Z",
2
+ "generatedAt": "2026-06-17T08:41:12.192Z",
3
3
  "types": [
4
4
  {
5
5
  "name": "IkasProductAttributeDetail",
@@ -11771,511 +11771,6 @@
11771
11771
  }
11772
11772
  ],
11773
11773
  "filePath": "video/index.ts"
11774
- },
11775
- {
11776
- "name": "ThemeSetting",
11777
- "kind": "type",
11778
- "domain": "theme",
11779
- "properties": [
11780
- {
11781
- "name": "name",
11782
- "type": "string",
11783
- "optional": false
11784
- },
11785
- {
11786
- "name": "displayName",
11787
- "type": "string",
11788
- "optional": false
11789
- },
11790
- {
11791
- "name": "type",
11792
- "type": "GlobalVariableType",
11793
- "optional": false
11794
- },
11795
- {
11796
- "name": "value",
11797
- "type": "any",
11798
- "optional": false
11799
- }
11800
- ],
11801
- "filePath": "theme-globals.ts"
11802
- },
11803
- {
11804
- "name": "DesignToken",
11805
- "kind": "type",
11806
- "domain": "theme",
11807
- "properties": [
11808
- {
11809
- "name": "id",
11810
- "type": "string",
11811
- "optional": false
11812
- },
11813
- {
11814
- "name": "name",
11815
- "type": "string",
11816
- "optional": false
11817
- },
11818
- {
11819
- "name": "resolved",
11820
- "type": "string | null",
11821
- "optional": false
11822
- },
11823
- {
11824
- "name": "cssVar",
11825
- "type": "string",
11826
- "optional": false
11827
- }
11828
- ],
11829
- "filePath": "theme-globals.ts"
11830
- },
11831
- {
11832
- "name": "TypographyToken",
11833
- "kind": "type",
11834
- "domain": "theme",
11835
- "properties": [
11836
- {
11837
- "name": "id",
11838
- "type": "string",
11839
- "optional": false
11840
- },
11841
- {
11842
- "name": "name",
11843
- "type": "string",
11844
- "optional": false
11845
- },
11846
- {
11847
- "name": "resolved",
11848
- "type": "Record<string, string>",
11849
- "optional": false
11850
- },
11851
- {
11852
- "name": "className",
11853
- "type": "string",
11854
- "optional": false
11855
- }
11856
- ],
11857
- "filePath": "theme-globals.ts"
11858
- },
11859
- {
11860
- "name": "BreakpointToken",
11861
- "kind": "type",
11862
- "domain": "theme",
11863
- "properties": [
11864
- {
11865
- "name": "id",
11866
- "type": "string",
11867
- "optional": false
11868
- },
11869
- {
11870
- "name": "name",
11871
- "type": "string",
11872
- "optional": false
11873
- },
11874
- {
11875
- "name": "width",
11876
- "type": "number",
11877
- "optional": false
11878
- }
11879
- ],
11880
- "filePath": "theme-globals.ts"
11881
- },
11882
- {
11883
- "name": "KeyframeToken",
11884
- "kind": "type",
11885
- "domain": "theme",
11886
- "properties": [
11887
- {
11888
- "name": "id",
11889
- "type": "string",
11890
- "optional": false
11891
- },
11892
- {
11893
- "name": "name",
11894
- "type": "string",
11895
- "optional": false
11896
- },
11897
- {
11898
- "name": "type",
11899
- "type": "string",
11900
- "optional": false
11901
- },
11902
- {
11903
- "name": "ref",
11904
- "type": "string",
11905
- "optional": false
11906
- },
11907
- {
11908
- "name": "points",
11909
- "type": "{ point: string }[]",
11910
- "optional": true
11911
- }
11912
- ],
11913
- "filePath": "theme-globals.ts"
11914
- },
11915
- {
11916
- "name": "ColorSchemeToken",
11917
- "kind": "type",
11918
- "domain": "theme",
11919
- "properties": [
11920
- {
11921
- "name": "id",
11922
- "type": "string",
11923
- "optional": false
11924
- },
11925
- {
11926
- "name": "name",
11927
- "type": "string",
11928
- "optional": false
11929
- },
11930
- {
11931
- "name": "isDefault",
11932
- "type": "boolean",
11933
- "optional": false
11934
- },
11935
- {
11936
- "name": "className",
11937
- "type": "string",
11938
- "optional": false
11939
- },
11940
- {
11941
- "name": "colorsByScheme",
11942
- "type": "Record<string, { resolved: string | null; cssVar: string }>",
11943
- "optional": false
11944
- }
11945
- ],
11946
- "filePath": "theme-globals.ts"
11947
- },
11948
- {
11949
- "name": "ThemeGlobals",
11950
- "kind": "type",
11951
- "domain": "theme",
11952
- "properties": [
11953
- {
11954
- "name": "settings",
11955
- "type": "Record<string, ThemeSetting>",
11956
- "optional": false
11957
- },
11958
- {
11959
- "name": "colors",
11960
- "type": "DesignToken[]",
11961
- "optional": false
11962
- },
11963
- {
11964
- "name": "typography",
11965
- "type": "TypographyToken[]",
11966
- "optional": false
11967
- },
11968
- {
11969
- "name": "breakpoints",
11970
- "type": "BreakpointToken[]",
11971
- "optional": false
11972
- },
11973
- {
11974
- "name": "keyframes",
11975
- "type": "KeyframeToken[]",
11976
- "optional": false
11977
- },
11978
- {
11979
- "name": "colorSchemes",
11980
- "type": "{ schemes: { id: string; name: string }[]; values: ColorSchemeToken[] }",
11981
- "optional": false
11982
- }
11983
- ],
11984
- "filePath": "theme-globals.ts"
11985
- },
11986
- {
11987
- "name": "StyleValueLike",
11988
- "kind": "type",
11989
- "domain": "theme",
11990
- "properties": [
11991
- {
11992
- "name": "value",
11993
- "type": "any",
11994
- "optional": true
11995
- },
11996
- {
11997
- "name": "patternValueId",
11998
- "type": "string",
11999
- "optional": true
12000
- },
12001
- {
12002
- "name": "keyframeValueId",
12003
- "type": "string",
12004
- "optional": true
12005
- },
12006
- {
12007
- "name": "colorSchemeId",
12008
- "type": "string",
12009
- "optional": true
12010
- }
12011
- ],
12012
- "filePath": "theme-globals.ts"
12013
- },
12014
- {
12015
- "name": "StyleConditionLike",
12016
- "kind": "type",
12017
- "domain": "theme",
12018
- "properties": [
12019
- {
12020
- "name": "value",
12021
- "type": "StyleValueLike",
12022
- "optional": true
12023
- }
12024
- ],
12025
- "filePath": "theme-globals.ts"
12026
- },
12027
- {
12028
- "name": "ElementStyleLike",
12029
- "kind": "type",
12030
- "domain": "theme",
12031
- "properties": [
12032
- {
12033
- "name": "property",
12034
- "type": "string",
12035
- "optional": false
12036
- },
12037
- {
12038
- "name": "value",
12039
- "type": "StyleValueLike | StyleConditionLike[]",
12040
- "optional": true
12041
- }
12042
- ],
12043
- "filePath": "theme-globals.ts"
12044
- },
12045
- {
12046
- "name": "PatternValueLike",
12047
- "kind": "type",
12048
- "domain": "theme",
12049
- "properties": [
12050
- {
12051
- "name": "id",
12052
- "type": "string",
12053
- "optional": false
12054
- },
12055
- {
12056
- "name": "name",
12057
- "type": "string",
12058
- "optional": true
12059
- },
12060
- {
12061
- "name": "style",
12062
- "type": "ElementStyleLike",
12063
- "optional": true
12064
- }
12065
- ],
12066
- "filePath": "theme-globals.ts"
12067
- },
12068
- {
12069
- "name": "PatternElementLike",
12070
- "kind": "type",
12071
- "domain": "theme",
12072
- "properties": [
12073
- {
12074
- "name": "id",
12075
- "type": "string",
12076
- "optional": false
12077
- },
12078
- {
12079
- "name": "name",
12080
- "type": "string",
12081
- "optional": true
12082
- },
12083
- {
12084
- "name": "styles",
12085
- "type": "ElementStyleLike[]",
12086
- "optional": true
12087
- }
12088
- ],
12089
- "filePath": "theme-globals.ts"
12090
- },
12091
- {
12092
- "name": "ColorSchemeLike",
12093
- "kind": "type",
12094
- "domain": "theme",
12095
- "properties": [
12096
- {
12097
- "name": "id",
12098
- "type": "string",
12099
- "optional": false
12100
- },
12101
- {
12102
- "name": "name",
12103
- "type": "string",
12104
- "optional": true
12105
- }
12106
- ],
12107
- "filePath": "theme-globals.ts"
12108
- },
12109
- {
12110
- "name": "ColorSchemeValueColorLike",
12111
- "kind": "type",
12112
- "domain": "theme",
12113
- "properties": [
12114
- {
12115
- "name": "colorSchemeId",
12116
- "type": "string",
12117
- "optional": false
12118
- },
12119
- {
12120
- "name": "style",
12121
- "type": "StyleValueLike",
12122
- "optional": true
12123
- }
12124
- ],
12125
- "filePath": "theme-globals.ts"
12126
- },
12127
- {
12128
- "name": "ColorSchemeValueLike",
12129
- "kind": "type",
12130
- "domain": "theme",
12131
- "properties": [
12132
- {
12133
- "name": "id",
12134
- "type": "string",
12135
- "optional": false
12136
- },
12137
- {
12138
- "name": "name",
12139
- "type": "string",
12140
- "optional": true
12141
- },
12142
- {
12143
- "name": "isDefault",
12144
- "type": "boolean",
12145
- "optional": true
12146
- },
12147
- {
12148
- "name": "designAssetId",
12149
- "type": "string",
12150
- "optional": true
12151
- },
12152
- {
12153
- "name": "colors",
12154
- "type": "ColorSchemeValueColorLike[]",
12155
- "optional": true
12156
- }
12157
- ],
12158
- "filePath": "theme-globals.ts"
12159
- },
12160
- {
12161
- "name": "BreakpointLike",
12162
- "kind": "type",
12163
- "domain": "theme",
12164
- "properties": [
12165
- {
12166
- "name": "id",
12167
- "type": "string",
12168
- "optional": false
12169
- },
12170
- {
12171
- "name": "name",
12172
- "type": "string",
12173
- "optional": true
12174
- },
12175
- {
12176
- "name": "width",
12177
- "type": "number",
12178
- "optional": true
12179
- }
12180
- ],
12181
- "filePath": "theme-globals.ts"
12182
- },
12183
- {
12184
- "name": "KeyframePointLike",
12185
- "kind": "type",
12186
- "domain": "theme",
12187
- "properties": [
12188
- {
12189
- "name": "point",
12190
- "type": "string",
12191
- "optional": false
12192
- }
12193
- ],
12194
- "filePath": "theme-globals.ts"
12195
- },
12196
- {
12197
- "name": "KeyframeLike",
12198
- "kind": "type",
12199
- "domain": "theme",
12200
- "properties": [
12201
- {
12202
- "name": "id",
12203
- "type": "string",
12204
- "optional": false
12205
- },
12206
- {
12207
- "name": "name",
12208
- "type": "string",
12209
- "optional": true
12210
- },
12211
- {
12212
- "name": "type",
12213
- "type": "string",
12214
- "optional": true
12215
- },
12216
- {
12217
- "name": "points",
12218
- "type": "KeyframePointLike[]",
12219
- "optional": true
12220
- }
12221
- ],
12222
- "filePath": "theme-globals.ts"
12223
- },
12224
- {
12225
- "name": "VariableLike",
12226
- "kind": "type",
12227
- "domain": "theme",
12228
- "properties": [
12229
- {
12230
- "name": "id",
12231
- "type": "string",
12232
- "optional": true
12233
- },
12234
- {
12235
- "name": "variableName",
12236
- "type": "string",
12237
- "optional": true
12238
- },
12239
- {
12240
- "name": "displayName",
12241
- "type": "string",
12242
- "optional": true
12243
- },
12244
- {
12245
- "name": "variableType",
12246
- "type": "string",
12247
- "optional": true
12248
- },
12249
- {
12250
- "name": "defaultValue",
12251
- "type": "any",
12252
- "optional": true
12253
- },
12254
- {
12255
- "name": "isGlobal",
12256
- "type": "boolean",
12257
- "optional": true
12258
- }
12259
- ],
12260
- "filePath": "theme-globals.ts"
12261
- },
12262
- {
12263
- "name": "SerializableProject",
12264
- "kind": "type",
12265
- "domain": "theme",
12266
- "properties": [
12267
- {
12268
- "name": "globalsBlueprint",
12269
- "type": "{ module?: { variables?: VariableLike[] } }",
12270
- "optional": true
12271
- },
12272
- {
12273
- "name": "theme",
12274
- "type": "{\n breakpoints?: BreakpointLike[];\n keyframes?: KeyframeLike[];\n pattern?: {\n values?: PatternValueLike[];\n elements?: PatternElementLike[];\n colorSchemes?: ColorSchemeLike[];\n colorSchemeValues?: ColorSchemeValueLike[];\n };\n }",
12275
- "optional": true
12276
- }
12277
- ],
12278
- "filePath": "theme-globals.ts"
12279
11774
  }
12280
11775
  ]
12281
11776
  }
package/dist/index.js CHANGED
@@ -2227,7 +2227,7 @@ server.tool("get_framework_guide", "Get a framework guide on a specific topic (e
2227
2227
  };
2228
2228
  });
2229
2229
  // Tool: get_type_definition
2230
- server.tool("get_type_definition", "Get the full definition of a storefront type or enum by name. Shows all properties with types, extends, or enum values. Covers both runtime models (e.g. 'IkasProduct', 'IkasOrderStatus') and theme-globals tokens returned by the getters (e.g. 'ThemeSetting', 'DesignToken', 'TypographyToken', 'ColorSchemeToken', 'BreakpointToken', 'KeyframeToken'). If a type reports as not found, it may not be indexed yet — fall back to reading the package's `.d.ts` (e.g. `@ikas/bp-storefront-config`) rather than typing the value as `any`.", {
2230
+ server.tool("get_type_definition", "Get the full definition of a storefront type or enum by name (e.g. 'IkasProduct', 'IkasOrderStatus'). Shows all properties with types, extends, or enum values.", {
2231
2231
  name: z
2232
2232
  .string()
2233
2233
  .describe("Type or enum name (e.g. 'IkasProduct', 'IkasOrderStatus')"),
@@ -3739,7 +3739,7 @@ server.tool("get_section_values", "Get the CURRENT prop values of one or MANY pl
3739
3739
  return callEditorAction(project_root, args);
3740
3740
  });
3741
3741
  // Tool: update_section_prop
3742
- server.tool("update_section_prop", 'Change a single prop value of a section placed on a page. This is the tool for FILLING/SETTING content (heading, text, image, link, etc.) on an existing section — it is pure data entry: it writes NO component code and needs NO rebuild. Do not author a new prop or component to set a value the section already supports; first check the section\'s existing `props` via `list_page_sections`. Target the specific placement by its `element_id` (from `list_page_sections`) and the prop by `prop_id` or `prop_name` (also from `list_page_sections`). `value` is the prop value object as stored by the editor — for scalar props it is wrapped as `{ "value": <scalar> }` (e.g. `{ "value": "Hello" }` for TEXT, `{ "value": true }` for BOOLEAN, `{ "value": 12 }` for NUMBER, `{ "value": "#FF0000" }` for COLOR, `{ "value": "<enum-key>" }` for ENUM). Richer object prop types use their own object shape and are NOT `{ "value": ... }`-wrapped (full catalog in `get_editor_workflow`): IMAGE = `{ "id": "<asset-id>", "altText"?: "<alt>", "isVideo"?: false }` (the `id` MUST reference an already-uploaded asset — call `upload_image` with a `file_path`/`image_url` to get one, or reuse an existing `id` from another section\'s `propValues`); IMAGE_LIST = `{ "images": [ <image>, ... ] }`; VIDEO = `{ "video": { "id": "<asset-id>" }, "thumbnailImage"?: { "id": "..." }, "autoplay"?: false, "controls"?: true, "loop"?: false, "muted"?: false }` (NOT a bare `{ "id": ... }`); SVG = `{ "value": "<svg markup>" }` (value-wrapped, like a scalar); SVG_LIST = `{ "svgs": [ "<svg>", ... ] }`; entity props PRODUCT/CATEGORY/BRAND/BLOG/BLOG_CATEGORY/RAFFLE = `{ "<entity>Id": "...", "usePageData"?: false }` (e.g. `{ "categoryId": "..." }`) — get real ids from `search_products` (PRODUCT), `list_categories`, `list_brands`, `list_blogs`, `list_blog_categories`; list/collection props are typed objects keyed by a `<entity>ListType` discriminator: PRODUCT_LIST = `{ "id": "<unique>", "productListType": "STATIC", "productIds": [ { "productId": "...", "variantId": "..." } ], "initialLimit"?: 12 }` — note productIds is an array of {productId, variantId} PAIRS (from search_products), not bare ids; productListType ∈ ALL|STATIC|DISCOUNTED|RECOMMENDED|CATEGORY|SEARCH|LAST_VIEWED|RELATED_PRODUCTS|VIEWED_TOGETHER|PURCHASED_TOGETHER, and for a dynamic type use e.g. `{ "id": "<unique>", "productListType": "CATEGORY", "category": "<categoryId>" }` (no productIds) or `"ALL"` (no ids). CATEGORY_LIST = `{ "categoryListType": "STATIC", "categoryIds": ["..."] }` or `{ "categoryListType": "ALL" }`. BRAND_LIST = `{ "brandListType": "STATIC", "brandIds": ["..."] }` or ALL. BLOG_LIST = `{ "blogListType": "STATIC", "blogIds": ["..."] }`, `{ "blogListType": "CATEGORY", "categoryId": "..." }`, or ALL. BLOG_CATEGORY_LIST = `{ "blogCategoryListType": "STATIC", "blogCategoryIds": ["..."] }` or ALL. (Get the entity ids from search_products / list_*; you can also read an existing value with `get_section_values` to copy its exact shape.) LINK = a single link object `{ "id": "<unique-short-id>", "linkType": "PAGE"|"EXTERNAL"|"FILE", "label": "...", "openInNewTab"?: false, "subLinks": [] }` plus the target for its type — for PAGE add `"pageId"` AND `"pageType"` (both from `list_editor_pages`, e.g. pageType "INDEX"; for dynamic page types like PRODUCT/CATEGORY/BLOG also add the target `"itemId"`), for EXTERNAL add `"externalLink": "https://..."`. Examples: PAGE → `{ "id": "k3p9x", "linkType": "PAGE", "label": "Home", "pageId": "<page-id>", "pageType": "INDEX", "openInNewTab": false, "subLinks": [] }`; EXTERNAL → `{ "id": "m7q2z", "linkType": "EXTERNAL", "label": "Docs", "externalLink": "https://example.com", "openInNewTab": true, "subLinks": [] }`. To link to an ENTITY (category/brand/blog/blog-category) do NOT guess a slug — get the entity id from `list_categories`/`list_brands`/`list_blogs`/`list_blog_categories` and the page id from `get_page_by_type("<TYPE>")`, then build `{ "id": "<unique>", "linkType": "PAGE", "label": "...", "pageId": <pageId>, "pageType": "<TYPE>", "itemId": <entityId>, "subLinks": [] }`. LIST_OF_LINK = `{ "links": [ <link>, ... ] }` (each item is a link object as above). PRODUCT = `{ "productId": "...", "variantId"?: "..." }`. This SAME unwrapped shape applies whether the prop sits at section level OR nested inside a COMPONENT_LIST entry\'s `propValues` — there is no section-vs-nested difference. IMPORTANT: pass `value` as the parsed JSON object/array itself, NEVER as a JSON string (a stringified value is double-encoded and stored as a useless string). Values are validated server-side (deeply, including nested COMPONENT_LIST children): wrong shapes AND wrong semantics are REJECTED with an explanatory error instead of being silently stored. This includes: a `{ "value": [...] }` wrapper for a COMPONENT_LIST; a `{ "value": ... }`-wrapped IMAGE; `props` instead of `propValues`; a missing/duplicate entry `id`; a child referenced by the wrong key (a code component MUST use `codeComponentId`, a theme component `componentId`) or by an id that does not exist (child ids are opaque — take them from `get_section_template` / `list_imported_sections`, never invent them); and any `propValues` key that is not a real prop of that child component (the error lists the valid prop names). Auto-import: a referenced child code component that has been BUILT but not yet imported into the theme is imported automatically before the value is set (the response lists any such ids under `autoImported`); only children that are not built at all fail with a "no imported code component" error — build them first (`ikas-component build`/`dev`). For any prop type you are unsure about, inspect the existing value with `get_section_values` and match its exact shape. The change is applied with undo support.\n\n' +
3742
+ server.tool("update_section_prop", 'Change a single prop value of a section placed on a page. This is the tool for FILLING/SETTING content (heading, text, image, link, etc.) on an existing section — it is pure data entry: it writes NO component code and needs NO rebuild. Do not author a new prop or component to set a value the section already supports; first check the section\'s existing `props` via `list_page_sections`. Target the specific placement by its `element_id` (from `list_page_sections`) and the prop by `prop_id` or `prop_name` (also from `list_page_sections`). `value` is the prop value object as stored by the editor — for scalar props it is wrapped as `{ "value": <scalar> }` (e.g. `{ "value": "Hello" }` for TEXT, `{ "value": true }` for BOOLEAN, `{ "value": 12 }` for NUMBER, `{ "value": "#FF0000" }` for COLOR, `{ "value": "<enum-key>" }` for ENUM). Richer object prop types use their own object shape and are NOT `{ "value": ... }`-wrapped (full catalog in `get_editor_workflow`): IMAGE = `{ "id": "<asset-id>", "altText"?: "<alt>", "isVideo"?: false }` (the `id` MUST reference an already-uploaded asset — call `upload_image` with a `file_path`/`image_url` to get one, or reuse an existing `id` from another section\'s `propValues`); IMAGE_LIST = `{ "images": [ <image>, ... ] }`; VIDEO = `{ "video": { "id": "<asset-id>" }, "thumbnailImage"?: { "id": "..." }, "autoplay"?: false, "controls"?: true, "loop"?: false, "muted"?: false }` (NOT a bare `{ "id": ... }`); SVG = `{ "value": "<svg markup>" }` (value-wrapped, like a scalar); SVG_LIST = `{ "svgs": [ "<svg>", ... ] }`; entity props PRODUCT/CATEGORY/BRAND/BLOG/BLOG_CATEGORY/RAFFLE = `{ "<entity>Id": "...", "usePageData"?: false }` (e.g. `{ "categoryId": "..." }`) — get real ids from `search_products` (PRODUCT), `list_categories`, `list_brands`, `list_blogs`, `list_blog_categories`; list/collection props are typed objects keyed by a `<entity>ListType` discriminator: PRODUCT_LIST = `{ "id": "<unique>", "productListType": "STATIC", "productIds": [ { "productId": "...", "variantId": "..." } ], "initialLimit"?: 12 }` — note productIds is an array of {productId, variantId} PAIRS (from search_products), not bare ids; productListType ∈ ALL|STATIC|DISCOUNTED|RECOMMENDED|CATEGORY|SEARCH|LAST_VIEWED|RELATED_PRODUCTS|VIEWED_TOGETHER|PURCHASED_TOGETHER, and for a dynamic type use e.g. `{ "id": "<unique>", "productListType": "CATEGORY", "category": "<id from list_categories>" }` (the field is `category`, NOT `categoryId` — `categoryId` is only the standalone CATEGORY entity prop; no productIds here) or `"ALL"` (no ids). Unknown sub-fields inside a PRODUCT_LIST (e.g. `categoryId`) are REJECTED, not silently stored. CATEGORY_LIST = `{ "categoryListType": "STATIC", "categoryIds": ["..."] }` or `{ "categoryListType": "ALL" }`. BRAND_LIST = `{ "brandListType": "STATIC", "brandIds": ["..."] }` or ALL. BLOG_LIST = `{ "blogListType": "STATIC", "blogIds": ["..."] }`, `{ "blogListType": "CATEGORY", "categoryId": "..." }`, or ALL. BLOG_CATEGORY_LIST = `{ "blogCategoryListType": "STATIC", "blogCategoryIds": ["..."] }` or ALL. (Get the entity ids from search_products / list_*; you can also read an existing value with `get_section_values` to copy its exact shape.) LINK = a single link object `{ "id": "<unique-short-id>", "linkType": "PAGE"|"EXTERNAL"|"FILE", "label": "...", "openInNewTab"?: false, "subLinks": [] }` plus the target for its type — for PAGE add `"pageId"` AND `"pageType"` (both from `list_editor_pages`, e.g. pageType "INDEX"; for dynamic page types like PRODUCT/CATEGORY/BLOG also add the target `"itemId"`), for EXTERNAL add `"externalLink": "https://..."`. Examples: PAGE → `{ "id": "k3p9x", "linkType": "PAGE", "label": "Home", "pageId": "<page-id>", "pageType": "INDEX", "openInNewTab": false, "subLinks": [] }`; EXTERNAL → `{ "id": "m7q2z", "linkType": "EXTERNAL", "label": "Docs", "externalLink": "https://example.com", "openInNewTab": true, "subLinks": [] }`. To link to an ENTITY (category/brand/blog/blog-category) do NOT guess a slug — get the entity id from `list_categories`/`list_brands`/`list_blogs`/`list_blog_categories` and the page id from `get_page_by_type("<TYPE>")`, then build `{ "id": "<unique>", "linkType": "PAGE", "label": "...", "pageId": <pageId>, "pageType": "<TYPE>", "itemId": <entityId>, "subLinks": [] }`. LIST_OF_LINK = `{ "links": [ <link>, ... ] }` (each item is a link object as above). PRODUCT = `{ "productId": "...", "variantId"?: "..." }`. This SAME unwrapped shape applies whether the prop sits at section level OR nested inside a COMPONENT_LIST entry\'s `propValues` — there is no section-vs-nested difference. IMPORTANT: pass `value` as the parsed JSON object/array itself, NEVER as a JSON string (a stringified value is double-encoded and stored as a useless string). Values are validated server-side (deeply, including nested COMPONENT_LIST children): wrong shapes AND wrong semantics are REJECTED with an explanatory error instead of being silently stored. This includes: a `{ "value": [...] }` wrapper for a COMPONENT_LIST; a `{ "value": ... }`-wrapped IMAGE; `props` instead of `propValues`; a missing/duplicate entry `id`; a child referenced by the wrong key (a code component MUST use `codeComponentId`, a theme component `componentId`) or by an id that does not exist (child ids are opaque — take them from `get_section_template` / `list_imported_sections`, never invent them); and any `propValues` key that is not a real prop of that child component (the error lists the valid prop names). Auto-import: a referenced child code component that has been BUILT but not yet imported into the theme is imported automatically before the value is set (the response lists any such ids under `autoImported`); only children that are not built at all fail with a "no imported code component" error — build them first (`ikas-component build`/`dev`). For any prop type you are unsure about, inspect the existing value with `get_section_values` and match its exact shape. The change is applied with undo support.\n\n' +
3743
3743
  'COMPONENT_LIST / COMPONENT props: the value is NOT wrapped in `{ "value": ... }`. A COMPONENT_LIST value is `{ "components": [ <entry>, ... ] }`; a single COMPONENT value is one `<entry>`. Each entry = `{ "id": "<unique-id>", "codeComponentId": "<child-id>" | "componentId": "<child-id>", "propValues": { "<childPropName>": <wrapped-value>, ... } }`. Rules: (1) `id` is a unique short alphanumeric string identifying THIS entry — generate a fresh one per new entry and NEVER reuse an existing entry\'s id. (2) Use `codeComponentId` for code components, `componentId` for built-in theme components. (3) `propValues` is keyed by the CHILD component\'s prop NAMES, each using the same scalar wrappers as above (nesting is recursive — a child may itself hold a COMPONENT_LIST). (4) `update_section_prop` REPLACES the whole prop value — there is NO partial/deep merge. ALWAYS send the COMPLETE, fully-nested value for the prop: every existing entry (with its id), every nested `propValues`, and every nested COMPONENT_LIST at every depth. To change anything (even one deeply-nested scalar, or to add/remove/reorder a child), READ-MODIFY-WRITE: take the current `{ "components": [...] }` from `get_section_values`, edit it in place (preserving all other entries, ids, and nested structures), then send the ENTIRE updated object back. Sending only the changed part — a single entry, or a child without its siblings — wipes everything you omitted. (5) You can only add child component types the prop permits — call `get_component_props(parentComponentId)` to read the COMPONENT_LIST prop\'s `allowedComponentIds`, then `get_component_props(childId)` to learn that child\'s props (names, types, ENUM `options`/valid values) instead of guessing or reading ikas.config.json. The allowed set is wired at build/config time per the `get_section_template` setup recipe (`config update-prop`), not here.\n\n' +
3744
3744
  'Example — a full COMPONENT_LIST `value` with two children, where the second child itself nests another COMPONENT_LIST (note: scalar leaves are `{ "value": ... }`-wrapped, COMPONENT_LIST values are `{ "components": [...] }` and are NOT wrapped, every entry has a unique `id`, and this is the COMPLETE value you would send even to change just one field): ' +
3745
3745
  `{ "components": [ { "id": "a1b2c", "codeComponentId": "7ojrigep-Eml9n5sN3i", "propValues": { "heading": { "value": "Featured" }, "visible": { "value": true } } }, { "id": "d3e4f", "codeComponentId": "x2plk9zq-Qw8rt", "propValues": { "title": { "value": "Sub group" }, "cards": { "components": [ { "id": "g5h6i", "codeComponentId": "card01ab-Zz12", "propValues": { "label": { "value": "Card 1" } } }, { "id": "j7k8l", "codeComponentId": "card01ab-Zz12", "propValues": { "label": { "value": "Card 2" } } } ] } } } ] }`, {
@@ -4027,7 +4027,7 @@ const EDITOR_WORKFLOW_GUIDE = [
4027
4027
  " - VIDEO: { \"video\": { \"id\": \"<asset-id>\" }, \"thumbnailImage\"?: { \"id\": \"...\" }, \"autoplay\"?: false, \"controls\"?: true, \"loop\"?: false, \"muted\"?: false } — NOT a bare { \"id\": ... }. SVG_LIST: { \"svgs\": [ \"<svg>\", ... ] }.",
4028
4028
  " - LINK: { \"id\": \"<unique>\", \"linkType\": \"PAGE\"|\"EXTERNAL\"|\"FILE\", \"label\": \"...\", \"subLinks\": [] } plus target — for a static page: pageId + pageType (from list_editor_pages); for EXTERNAL: externalLink. To link to a CATEGORY/BRAND/BLOG/BLOG_CATEGORY entity, do NOT guess a slug — get the entity id from list_categories/list_brands/list_blogs/list_blog_categories and the page id from get_page_by_type('<TYPE>'), then build { id, linkType:'PAGE', label, pageId:<pageId>, pageType:'<TYPE>', itemId:<entityId>, subLinks:[] }. LIST_OF_LINK = { \"links\": [ <link>, ... ] }.",
4029
4029
  " - Entity props PRODUCT/CATEGORY/BRAND/BLOG/BLOG_CATEGORY/RAFFLE: { \"<entity>Id\": \"...\", \"usePageData\"?: false } — e.g. { \"productId\": \"...\", \"variantId\"?: \"...\" }, { \"categoryId\": \"...\" }. Get real ids (never invent them) from: search_products (PRODUCT), list_categories (CATEGORY), list_brands (BRAND), list_blogs (BLOG), list_blog_categories (BLOG_CATEGORY). (RAFFLE has no lookup tool yet — read an existing value or ask the user.)",
4030
- " - List/collection props (PRODUCT_LIST/CATEGORY_LIST/BRAND_LIST/BLOG_LIST/…): complex typed objects (a <entity>ListType plus initialSort/initialLimit and static ids). Do NOT build from scratch — read the current value with get_section_values and edit it.",
4030
+ " - List/collection props (PRODUCT_LIST/CATEGORY_LIST/BRAND_LIST/BLOG_LIST/…): typed objects keyed by a <entity>ListType discriminator plus initialSort/initialLimit. The id field DEPENDS on the type — for PRODUCT_LIST: STATIC → productIds:[{productId,variantId}] (from search_products); CATEGORY → category:'<categoryId>' (from list_categories) — the field is `category`, NOT `categoryId` (categoryId is ONLY the standalone CATEGORY entity prop above); ALL/DISCOUNTED/RECOMMENDED/etc → no id field. Get the exact field set + writeNote from get_component_props, or read+edit an existing value via get_section_values. Unknown sub-fields (e.g. categoryId inside a PRODUCT_LIST) are REJECTED.",
4031
4031
  " - COMPONENT_LIST: { \"components\": [ { \"id\": \"<unique>\", \"codeComponentId\": \"<child-id>\", \"propValues\": { \"<childProp>\": <value>, ... } }, ... ] }. A single COMPONENT prop is one such entry. childProp values use these same per-type shapes, recursively.",
4032
4032
  "",
4033
4033
  "## COMPONENT_LIST rules (the part most often gotten wrong)",
@@ -4050,7 +4050,7 @@ server.tool("get_editor_workflow", "Read this FIRST when the user wants to place
4050
4050
  return { content: [{ type: "text", text: EDITOR_WORKFLOW_GUIDE }] };
4051
4051
  });
4052
4052
  // Tool: list_theme_globals
4053
- server.tool("list_theme_globals", "List the theme's global settings from the connected editor: global variables (Theme Settings) and design tokens (colors, typography, breakpoints, keyframes, color schemes). Call this BEFORE generating sections/components so you reuse the theme's existing variables and tokens (read them in component code via `getThemeSetting`/`getThemeColors`/... from `@ikas/bp-storefront`). Includes items created manually in the editor UI. Requires `ikas-component dev` running with the editor connected. Two shape gotchas when consuming the result at runtime: (1) color schemes — `colorSchemes.schemes` holds only `{id,name}` slot LABELS; the actual colors live in `colorSchemes.values[].colorsByScheme` keyed by slot id, so iterate `values[].colorsByScheme` (iterating `schemes` renders empty). (2) An IMAGE setting's `value` is an image REFERENCE like `{id:'theme-images/<uuid>'}` with no `.url` — resolve it via `getDefaultSrc`/`getSrc`.", {
4053
+ server.tool("list_theme_globals", "List the theme's global settings from the connected editor: global variables (Theme Settings) and design tokens (colors, typography, breakpoints, keyframes, color schemes). Call this BEFORE generating sections/components so you reuse the theme's existing variables and tokens (read them in component code via `getThemeSetting`/`getThemeColors`/... from `@ikas/bp-storefront`). Includes items created manually in the editor UI. Requires `ikas-component dev` running with the editor connected.", {
4054
4054
  project_root: z.string().describe("Absolute path to the code-component project (where `node_modules/.bin/ikas-component` lives)."),
4055
4055
  port: z.number().optional().describe("Dev server WebSocket port (default 5201)."),
4056
4056
  }, async ({ project_root, port }) => {