@agimon-ai/style-system 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +52 -0
- package/README.md +148 -0
- package/dist/cli.cjs +412 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +393 -0
- package/dist/index.cjs +84 -0
- package/dist/index.d.cts +1959 -0
- package/dist/index.d.mts +1959 -0
- package/dist/index.mjs +2 -0
- package/dist/shims/expo-symbols.ts +9 -0
- package/dist/shims/expo-vector-icons.ts +36 -0
- package/dist/shims/react-native-reanimated.ts +57 -0
- package/dist/stdio-Bh4OBwmR.mjs +5288 -0
- package/dist/stdio-D8AH3sRD.cjs +5529 -0
- package/package.json +89 -0
- package/skills/style-system/SKILL.md +83 -0
- package/skills/style-system/agents/openai.yaml +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: AgiFlow
|
|
6
|
+
Licensed Work: @agimon-ai/public-packages
|
|
7
|
+
The Licensed Work is (c) 2026 AgiFlow.
|
|
8
|
+
Additional Use Grant: None
|
|
9
|
+
Change Date: 2030-03-06
|
|
10
|
+
Change License: Apache License, Version 2.0
|
|
11
|
+
|
|
12
|
+
Terms
|
|
13
|
+
|
|
14
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
15
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
16
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
17
|
+
production use.
|
|
18
|
+
|
|
19
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
20
|
+
available distribution of a specific version of the Licensed Work under this
|
|
21
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
22
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
23
|
+
above terminate.
|
|
24
|
+
|
|
25
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
26
|
+
currently in effect as described in this License, you must purchase a
|
|
27
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
28
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
29
|
+
|
|
30
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
31
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
32
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
33
|
+
for each version of the Licensed Work released by Licensor.
|
|
34
|
+
|
|
35
|
+
You must conspicuously display this License on each original or modified copy
|
|
36
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
37
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
38
|
+
License apply to your use of that work.
|
|
39
|
+
|
|
40
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
41
|
+
terminate your rights under this License for the current and all other
|
|
42
|
+
versions of the Licensed Work.
|
|
43
|
+
|
|
44
|
+
This License does not grant you any right in any trademark or logo of
|
|
45
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
46
|
+
Licensor as expressly required by this License).
|
|
47
|
+
|
|
48
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
49
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
52
|
+
TITLE.
|
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @agimon-ai/style-system
|
|
2
|
+
|
|
3
|
+
MCP server and CLI for exploring themes, Tailwind CSS classes, and UI components from Storybook, with
|
|
4
|
+
standalone component rendering.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add -D @agimon-ai/style-system
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## CLI
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
style-system --help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Command | Purpose |
|
|
19
|
+
| ------------------------ | ----------------------------------------------------------------------- |
|
|
20
|
+
| `get-css-classes` | Extract the valid CSS classes from a theme CSS file |
|
|
21
|
+
| `get-ui-component` | Render a component to a screenshot using the app's design-system config |
|
|
22
|
+
| `list-app-components` | List app-specific components and package components |
|
|
23
|
+
| `polish-component` | Design-system-aware component polish |
|
|
24
|
+
| `generate-oxlint-config` | Generate an oxlint `no-restricted-classes` config from theme tokens |
|
|
25
|
+
| `mcp-serve` | Run as an MCP server over stdio |
|
|
26
|
+
|
|
27
|
+
## MCP server
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"mcpServers": {
|
|
32
|
+
"style-system": {
|
|
33
|
+
"command": "npx",
|
|
34
|
+
"args": ["-y", "@agimon-ai/style-system", "mcp-serve"]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Configuration
|
|
41
|
+
|
|
42
|
+
Configuration lives in files named `style-system.config.yaml`, at two levels:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
<workspace-root>/style-system.config.yaml # defines defaults and presets
|
|
46
|
+
<project>/style-system.config.yaml # selects a preset, applies overrides
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The workspace root is found by walking up from the current working directory until a `.git`
|
|
50
|
+
directory is found, falling back to the working directory itself. It is your repository root, not
|
|
51
|
+
the installed package location.
|
|
52
|
+
|
|
53
|
+
### Resolution order
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
built-in defaults -> root `defaults` -> preset chain (parents before child) -> project config
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Last wins, and **fields replace wholesale**. Lists and objects are never merged element-wise, so a
|
|
60
|
+
project that sets `cssFiles` replaces the inherited list entirely. Use `cssFiles: []` to clear one.
|
|
61
|
+
|
|
62
|
+
Every field is optional in any individual file. Required-ness is enforced against the merged result,
|
|
63
|
+
so a project config can be valid while inheriting nearly everything.
|
|
64
|
+
|
|
65
|
+
Both schemas are strict: an unknown or misspelled key is a hard error rather than a silent no-op. The
|
|
66
|
+
project schema additionally rejects `root`, `defaults` and `presets`, so the two file types can never
|
|
67
|
+
be confused for one another.
|
|
68
|
+
|
|
69
|
+
### Workspace root file
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
# <workspace-root>/style-system.config.yaml
|
|
73
|
+
root: true # required literal; marks this as the workspace file
|
|
74
|
+
|
|
75
|
+
# Story tags that mark a component as shared/design-system.
|
|
76
|
+
sharedComponentTags:
|
|
77
|
+
- style-system
|
|
78
|
+
|
|
79
|
+
# Optional service overrides. Paths are workspace-root relative.
|
|
80
|
+
# getCssClasses:
|
|
81
|
+
# customService: packages/.../CustomCSSClassesService.ts
|
|
82
|
+
# bundler:
|
|
83
|
+
# customService: packages/.../CustomBundlerService.ts
|
|
84
|
+
|
|
85
|
+
# Applied to every project, beneath its preset chain.
|
|
86
|
+
defaults:
|
|
87
|
+
type: tailwind
|
|
88
|
+
colorScheme: automatic
|
|
89
|
+
|
|
90
|
+
presets:
|
|
91
|
+
web-app:
|
|
92
|
+
viewport: { width: 1280, height: 800 }
|
|
93
|
+
cssFiles: ['src/assets/main.css']
|
|
94
|
+
componentLibrary: '@acme/web-ui'
|
|
95
|
+
mcp-app:
|
|
96
|
+
extends: web-app # presets may extend other presets
|
|
97
|
+
rootComponent: 'src/components/Root/index.tsx'
|
|
98
|
+
native-app:
|
|
99
|
+
bundler: vite-react-native
|
|
100
|
+
unistylesConfig: unistyles.ts
|
|
101
|
+
viewport: { width: 393, height: 852 }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Project file
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
# <project>/style-system.config.yaml
|
|
108
|
+
extends: web-app # a preset name, or a list: [base, overrides]
|
|
109
|
+
viewport: { width: 1440, height: 900 }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Fields
|
|
113
|
+
|
|
114
|
+
| Field | Type | Purpose |
|
|
115
|
+
| --------------------- | -------------------------------- | -------------------------------------------------- |
|
|
116
|
+
| `type` | `tailwind` \| `shadcn` | Design system flavour |
|
|
117
|
+
| `bundler` | string | Bundler strategy, e.g. `vite-react-native` |
|
|
118
|
+
| `brand` | string | Brand identifier |
|
|
119
|
+
| `unistylesConfig` | string | Path to the Unistyles config, for native rendering |
|
|
120
|
+
| `colorScheme` | `automatic` \| `light` \| `dark` | Rendering colour scheme |
|
|
121
|
+
| `viewport` | `{ width, height }` | Screenshot viewport, positive integers |
|
|
122
|
+
| `tailwindConfig` | string | Path to a Tailwind config |
|
|
123
|
+
| `themeProvider` | string | Module providing the theme provider component |
|
|
124
|
+
| `rootComponent` | string | Root component wrapped around rendered stories |
|
|
125
|
+
| `cssFiles` | string[] | Stylesheets loaded before rendering |
|
|
126
|
+
| `componentLibrary` | string | Package holding shared components |
|
|
127
|
+
| `themePath` | string | Path to the theme CSS |
|
|
128
|
+
| `sharedComponentTags` | string[] | Story tags marking a component as shared |
|
|
129
|
+
|
|
130
|
+
`bundler` is shape-dependent on level: in `defaults`, a preset, or a project file it is a **string**
|
|
131
|
+
naming the strategy; at the workspace root, alongside `getCssClasses`, it is a **service override
|
|
132
|
+
object** taking `customService`.
|
|
133
|
+
|
|
134
|
+
## Native rendering
|
|
135
|
+
|
|
136
|
+
Rendering React Native stories additionally requires the application being rendered to provide
|
|
137
|
+
`react-native`, `react-native-unistyles`, `react-native-reanimated`, `@babel/core`,
|
|
138
|
+
`expo-modules-core` and `@expo/vector-icons`. These are resolved from the target application's
|
|
139
|
+
directory, not from this package, so a React Native app already satisfies them.
|
|
140
|
+
|
|
141
|
+
## Agent skill
|
|
142
|
+
|
|
143
|
+
The published package ships a `skills/style-system` skill describing when and how an agent should use
|
|
144
|
+
these commands.
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_stdio = require("./stdio-D8AH3sRD.cjs");
|
|
3
|
+
let node_fs = require("node:fs");
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
node_path = require_stdio.__toESM(node_path, 1);
|
|
6
|
+
let _agimon_ai_foundation_exec = require("@agimon-ai/foundation-exec");
|
|
7
|
+
require("reflect-metadata");
|
|
8
|
+
let commander = require("commander");
|
|
9
|
+
let chalk = require("chalk");
|
|
10
|
+
chalk = require_stdio.__toESM(chalk, 1);
|
|
11
|
+
//#region src/utils/print.ts
|
|
12
|
+
function resolveChalk(value, depth = 0) {
|
|
13
|
+
if (value && (typeof value === "object" || typeof value === "function") && "red" in value && typeof value.red === "function") return value;
|
|
14
|
+
if (depth < 3 && value && (typeof value === "object" || typeof value === "function") && "default" in value) return resolveChalk(value.default, depth + 1);
|
|
15
|
+
throw new Error("Unable to resolve chalk instance");
|
|
16
|
+
}
|
|
17
|
+
const chalk$1 = resolveChalk(chalk);
|
|
18
|
+
const print = {
|
|
19
|
+
info: (message) => {
|
|
20
|
+
console.log(chalk$1.cyan(message));
|
|
21
|
+
},
|
|
22
|
+
success: (message) => {
|
|
23
|
+
console.log(chalk$1.green(message));
|
|
24
|
+
},
|
|
25
|
+
warning: (message) => {
|
|
26
|
+
console.log(chalk$1.yellow(message));
|
|
27
|
+
},
|
|
28
|
+
error: (message, error) => {
|
|
29
|
+
if (error) {
|
|
30
|
+
const errorMsg = error instanceof Error ? error.message : error;
|
|
31
|
+
console.error(chalk$1.red(message), errorMsg);
|
|
32
|
+
} else console.error(chalk$1.red(message));
|
|
33
|
+
},
|
|
34
|
+
debug: (message) => {
|
|
35
|
+
console.log(chalk$1.gray(message));
|
|
36
|
+
},
|
|
37
|
+
header: (message) => {
|
|
38
|
+
console.log(chalk$1.bold.cyan(message));
|
|
39
|
+
},
|
|
40
|
+
item: (message) => {
|
|
41
|
+
console.log(chalk$1.white(` - ${message}`));
|
|
42
|
+
},
|
|
43
|
+
indent: (message) => {
|
|
44
|
+
console.log(chalk$1.white(` ${message}`));
|
|
45
|
+
},
|
|
46
|
+
highlight: (message) => {
|
|
47
|
+
console.log(chalk$1.bold.green(message));
|
|
48
|
+
},
|
|
49
|
+
newline: () => {
|
|
50
|
+
console.log();
|
|
51
|
+
},
|
|
52
|
+
divider: () => {
|
|
53
|
+
console.log(chalk$1.gray(".".repeat(60)));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/commands/generate-oxlint-config.ts
|
|
58
|
+
/**
|
|
59
|
+
* Generate Oxlint Config Command
|
|
60
|
+
*
|
|
61
|
+
* DESIGN PATTERNS:
|
|
62
|
+
* - Command pattern with Commander for CLI argument parsing
|
|
63
|
+
* - Async/await pattern for asynchronous operations
|
|
64
|
+
* - Error handling pattern with try-catch and proper exit codes
|
|
65
|
+
*
|
|
66
|
+
* CODING STANDARDS:
|
|
67
|
+
* - Use async action handlers for asynchronous operations
|
|
68
|
+
* - Provide clear option descriptions and default values
|
|
69
|
+
* - Handle errors gracefully with process.exit()
|
|
70
|
+
* - Log progress and errors to console
|
|
71
|
+
* - Use Commander's .option() and .argument() for inputs
|
|
72
|
+
*
|
|
73
|
+
* AVOID:
|
|
74
|
+
* - Synchronous blocking operations in action handlers
|
|
75
|
+
* - Missing error handling (always use try-catch)
|
|
76
|
+
* - Hardcoded values (use options or environment variables)
|
|
77
|
+
* - Not exiting with appropriate exit codes on errors
|
|
78
|
+
*/
|
|
79
|
+
/**
|
|
80
|
+
* Generate oxlint no-restricted-classes config from theme CSS design tokens
|
|
81
|
+
*/
|
|
82
|
+
const generateOxlintConfigCommand = new commander.Command("generate-oxlint-config").description("Generate oxlint no-restricted-classes config from theme CSS design tokens").option("-a, --app-path <path>", "App path to read theme path from its style-system.config.yaml").option("-t, --theme-path <path>", "Theme CSS file path relative to workspace root").option("-o, --output <path>", "Output file path (defaults to stdout)").action(async (options) => {
|
|
83
|
+
try {
|
|
84
|
+
const themePath = (options.appPath ? (await require_stdio.getAppDesignSystemConfig(options.appPath)).themePath : void 0) ?? options.themePath;
|
|
85
|
+
if (!themePath) throw new Error("No theme CSS path resolved. Pass --theme-path, or pass --app-path for an app that configures themePath.");
|
|
86
|
+
const resolvedThemePath = await require_stdio.resolveStyleSystemThemePath({
|
|
87
|
+
appPath: options.appPath ?? null,
|
|
88
|
+
themePath
|
|
89
|
+
});
|
|
90
|
+
const cssResult = await new require_stdio.TailwindCSSClassesService(require_stdio.DEFAULT_STYLE_SYSTEM_CONFIG).extractClasses("colors", resolvedThemePath);
|
|
91
|
+
const config = require_stdio.generateRestrictedClassesConfig(cssResult);
|
|
92
|
+
const jsonOutput = JSON.stringify(config, null, 2);
|
|
93
|
+
if (options.output) {
|
|
94
|
+
const outputPath = node_path.default.resolve(options.output);
|
|
95
|
+
await node_fs.promises.writeFile(outputPath, `${jsonOutput}\n`, "utf-8");
|
|
96
|
+
print.success(`Config written to ${outputPath}`);
|
|
97
|
+
} else print.info(jsonOutput);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
print.error("Error generating oxlint config:", error instanceof Error ? error.message : String(error));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/commands/get-css-classes.ts
|
|
105
|
+
/**
|
|
106
|
+
* Get CSS Classes CLI Command
|
|
107
|
+
*/
|
|
108
|
+
const getCSSClassesCommand = new commander.Command("get-css-classes").description("Extract and return all valid CSS classes from a theme CSS file").option("-c, --category <category>", "Category filter: 'colors', 'typography', 'spacing', 'effects', 'all'", "all").option("-a, --app-path <path>", "App path to read theme path from style-system.config.yaml (e.g., \"apps/agiflow-app\")").option("-t, --theme-path <path>", "Theme CSS file path relative to workspace root (required unless appPath resolves themePath from style-system.config.yaml)").action(async (options) => {
|
|
109
|
+
try {
|
|
110
|
+
const result = await require_stdio.createContainer({ defaultThemePath: options.themePath }).get(require_stdio.STYLE_SYSTEM_TYPES.GetCSSClassesTool).execute({
|
|
111
|
+
category: options.category,
|
|
112
|
+
appPath: options.appPath
|
|
113
|
+
});
|
|
114
|
+
if (result.isError) {
|
|
115
|
+
const firstContent = result.content[0];
|
|
116
|
+
const errorText = firstContent?.type === "text" ? firstContent.text : "Unknown error";
|
|
117
|
+
throw new Error(errorText);
|
|
118
|
+
}
|
|
119
|
+
const firstContent = result.content[0];
|
|
120
|
+
print.info(firstContent?.type === "text" ? firstContent.text : "");
|
|
121
|
+
} catch (error) {
|
|
122
|
+
print.error("Error getting CSS classes:", error instanceof Error ? error.message : String(error));
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/commands/get-ui-component.ts
|
|
128
|
+
/**
|
|
129
|
+
* Get UI Component CLI Command
|
|
130
|
+
*/
|
|
131
|
+
const LIGHT_COLOR_SCHEME = "light";
|
|
132
|
+
const DARK_COLOR_SCHEME = "dark";
|
|
133
|
+
const REQUESTABLE_COLOR_SCHEMES = [LIGHT_COLOR_SCHEME, DARK_COLOR_SCHEME];
|
|
134
|
+
const getUiComponentCommand = new commander.Command("get-ui-component").description("Get a screenshot of a UI component rendered with app-specific design system configuration. Returns screenshot path and story file content.").requiredOption("-c, --component-name <name>", "The name of the component to capture (e.g., \"Button\", \"Card\")").requiredOption("-a, --app-path <path>", "The app path (relative or absolute) to load design system config from (e.g., \"apps/agiflow-app\")").option("-s, --story-name <name>", "The story name to render (e.g., \"Playground\", \"Default\")", "Playground").option("-d, --dark-mode", "Request dark mode for automatic-theme apps").option("--color-scheme <scheme>", "Request light or dark mode for automatic-theme apps").option("--width <pixels>", "Override the configured viewport width", Number).option("--height <pixels>", "Override the configured viewport height", Number).action(async (options) => {
|
|
135
|
+
try {
|
|
136
|
+
if (options.colorScheme !== void 0 && !REQUESTABLE_COLOR_SCHEMES.includes(options.colorScheme)) throw new Error("--color-scheme must be light or dark");
|
|
137
|
+
const tool = require_stdio.createContainer().get(require_stdio.STYLE_SYSTEM_TYPES.GetComponentVisualTool);
|
|
138
|
+
const darkMode = options.colorScheme === DARK_COLOR_SCHEME ? true : options.colorScheme === LIGHT_COLOR_SCHEME ? false : options.darkMode || void 0;
|
|
139
|
+
const result = await tool.execute({
|
|
140
|
+
componentName: options.componentName,
|
|
141
|
+
appPath: options.appPath,
|
|
142
|
+
storyName: options.storyName,
|
|
143
|
+
darkMode,
|
|
144
|
+
width: options.width,
|
|
145
|
+
height: options.height
|
|
146
|
+
});
|
|
147
|
+
if (result.isError) {
|
|
148
|
+
const firstContent = result.content[0];
|
|
149
|
+
const errorText = firstContent?.type === "text" ? firstContent.text : "Unknown error";
|
|
150
|
+
throw new Error(errorText);
|
|
151
|
+
}
|
|
152
|
+
const firstContent = result.content[0];
|
|
153
|
+
process.stdout.write(`${firstContent?.type === "text" ? firstContent.text : ""}\n`);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
156
|
+
require_stdio.log.error("Error:", errorMessage);
|
|
157
|
+
process.stderr.write(`${errorMessage.startsWith("Error:") ? errorMessage : `Error: ${errorMessage}`}\n`);
|
|
158
|
+
process.exitCode = 1;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/commands/list-app-components.ts
|
|
163
|
+
/**
|
|
164
|
+
* List App Components CLI Command
|
|
165
|
+
*/
|
|
166
|
+
const listAppComponentsCommand = new commander.Command("list-app-components").description("List app-specific components and package components. Reads the app's package.json to find workspace dependencies.").requiredOption("-a, --app-path <path>", "The app path (relative or absolute) to list components for (e.g., \"apps/agiflow-app\")").option("-c, --cursor <cursor>", "Pagination cursor to fetch the next page").action(async (options) => {
|
|
167
|
+
try {
|
|
168
|
+
const result = await require_stdio.createContainer().get(require_stdio.STYLE_SYSTEM_TYPES.ListAppComponentsTool).execute({
|
|
169
|
+
appPath: options.appPath,
|
|
170
|
+
cursor: options.cursor
|
|
171
|
+
});
|
|
172
|
+
if (result.isError) {
|
|
173
|
+
const firstContent = result.content[0];
|
|
174
|
+
const errorText = firstContent?.type === "text" ? firstContent.text : "Unknown error";
|
|
175
|
+
throw new Error(errorText);
|
|
176
|
+
}
|
|
177
|
+
const firstContent = result.content[0];
|
|
178
|
+
print.info(firstContent?.type === "text" ? firstContent.text : "");
|
|
179
|
+
} catch (error) {
|
|
180
|
+
print.error("Error:", error instanceof Error ? error.message : String(error));
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region src/commands/list-themes.ts
|
|
186
|
+
/**
|
|
187
|
+
* List Themes Command
|
|
188
|
+
*
|
|
189
|
+
* DESIGN PATTERNS:
|
|
190
|
+
* - Command pattern with Commander for CLI argument parsing
|
|
191
|
+
* - Async/await pattern for asynchronous operations
|
|
192
|
+
* - Error handling pattern with try-catch and proper exit codes
|
|
193
|
+
*
|
|
194
|
+
* CODING STANDARDS:
|
|
195
|
+
* - Use async action handlers for asynchronous operations
|
|
196
|
+
* - Provide clear option descriptions and default values
|
|
197
|
+
* - Handle errors gracefully with process.exit()
|
|
198
|
+
* - Log progress and errors to console
|
|
199
|
+
* - Use Commander's .option() and .argument() for inputs
|
|
200
|
+
*
|
|
201
|
+
* AVOID:
|
|
202
|
+
* - Synchronous blocking operations in action handlers
|
|
203
|
+
* - Missing error handling (always use try-catch)
|
|
204
|
+
* - Hardcoded values (use options or environment variables)
|
|
205
|
+
* - Not exiting with appropriate exit codes on errors
|
|
206
|
+
*/
|
|
207
|
+
/**
|
|
208
|
+
* List all available theme configurations from CSS files
|
|
209
|
+
*/
|
|
210
|
+
const listThemesCommand = new commander.Command("list-themes").description("List all available theme configurations from CSS files configured in style-system.config.yaml").option("-a, --app-path <path>", "App path to read theme config from style-system.config.yaml (e.g., \"apps/my-app\")").action(async (options) => {
|
|
211
|
+
try {
|
|
212
|
+
const result = await require_stdio.createContainer().get(require_stdio.STYLE_SYSTEM_TYPES.ListThemesTool).execute({ appPath: options.appPath });
|
|
213
|
+
if (result.isError) {
|
|
214
|
+
const firstContent = result.content[0];
|
|
215
|
+
const errorText = firstContent?.type === "text" ? firstContent.text : "Unknown error";
|
|
216
|
+
throw new Error(errorText);
|
|
217
|
+
}
|
|
218
|
+
const firstContent = result.content[0];
|
|
219
|
+
print.info(firstContent?.type === "text" ? firstContent.text : "");
|
|
220
|
+
} catch (error) {
|
|
221
|
+
print.error("Error listing themes:", error instanceof Error ? error.message : String(error));
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region src/commands/list-shared-components.ts
|
|
227
|
+
/**
|
|
228
|
+
* List Shared Components CLI Command
|
|
229
|
+
*/
|
|
230
|
+
const listSharedComponentsCommand = new commander.Command("list-shared-components").description("List all shared UI components available in the design system").option("-c, --cursor <cursor>", "Pagination cursor to fetch the next page").action(async (options) => {
|
|
231
|
+
try {
|
|
232
|
+
const result = await require_stdio.createContainer().get(require_stdio.STYLE_SYSTEM_TYPES.ListSharedComponentsTool).execute({ cursor: options.cursor });
|
|
233
|
+
if (result.isError) {
|
|
234
|
+
const firstContent = result.content[0];
|
|
235
|
+
const errorText = firstContent?.type === "text" ? firstContent.text : "Unknown error";
|
|
236
|
+
throw new Error(errorText);
|
|
237
|
+
}
|
|
238
|
+
const firstContent = result.content[0];
|
|
239
|
+
print.info(firstContent?.type === "text" ? firstContent.text : "");
|
|
240
|
+
} catch (error) {
|
|
241
|
+
print.error("Error listing shared components:", error instanceof Error ? error.message : String(error));
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/commands/mcp-serve.ts
|
|
247
|
+
/**
|
|
248
|
+
* MCP Serve Command
|
|
249
|
+
*
|
|
250
|
+
* DESIGN PATTERNS:
|
|
251
|
+
* - Command pattern with Commander for CLI argument parsing
|
|
252
|
+
* - Transport abstraction pattern for flexible deployment (stdio, HTTP, SSE)
|
|
253
|
+
* - Factory pattern for creating transport handlers
|
|
254
|
+
* - Graceful shutdown pattern with signal handling
|
|
255
|
+
*
|
|
256
|
+
* CODING STANDARDS:
|
|
257
|
+
* - Use async/await for asynchronous operations
|
|
258
|
+
* - Implement proper error handling with try-catch blocks
|
|
259
|
+
* - Handle process signals for graceful shutdown
|
|
260
|
+
* - Provide clear CLI options and help messages
|
|
261
|
+
*
|
|
262
|
+
* AVOID:
|
|
263
|
+
* - Hardcoded configuration values (use CLI options or environment variables)
|
|
264
|
+
* - Missing error handling for transport startup
|
|
265
|
+
* - Not cleaning up resources on shutdown
|
|
266
|
+
*/
|
|
267
|
+
/**
|
|
268
|
+
* Start MCP server with given transport handler
|
|
269
|
+
*/
|
|
270
|
+
async function startServer(handler, bundlerService, devServerPort) {
|
|
271
|
+
await handler.start();
|
|
272
|
+
let releaseProcess = async () => {};
|
|
273
|
+
try {
|
|
274
|
+
releaseProcess = await (0, _agimon_ai_foundation_exec.registerManagedProcess)({
|
|
275
|
+
repositoryPath: process.cwd(),
|
|
276
|
+
serviceName: "style-system-mcp",
|
|
277
|
+
serviceType: "tool",
|
|
278
|
+
environment: process.env["NODE_ENV"] ?? "development",
|
|
279
|
+
pid: process.pid,
|
|
280
|
+
port: devServerPort,
|
|
281
|
+
command: "style-system mcp-serve",
|
|
282
|
+
killOnRelease: true,
|
|
283
|
+
releasePortOnRelease: false,
|
|
284
|
+
metadata: devServerPort ? { devServerPort } : {}
|
|
285
|
+
});
|
|
286
|
+
} catch {}
|
|
287
|
+
const shutdown = async (signal) => {
|
|
288
|
+
console.error(`\nReceived ${signal}, shutting down gracefully...`);
|
|
289
|
+
try {
|
|
290
|
+
if (bundlerService.isServerRunning()) {
|
|
291
|
+
console.error("Stopping bundler dev server...");
|
|
292
|
+
await bundlerService.cleanup();
|
|
293
|
+
}
|
|
294
|
+
await releaseProcess();
|
|
295
|
+
await handler.stop();
|
|
296
|
+
process.exit(0);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
console.error("Error during shutdown:", error);
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
303
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* MCP Serve command
|
|
307
|
+
*
|
|
308
|
+
* Note: Design system configuration is now app-specific and read from each app's project.json.
|
|
309
|
+
* No global theme configuration is needed at the server level.
|
|
310
|
+
*/
|
|
311
|
+
const mcpServeCommand = new commander.Command("mcp-serve").description("Start MCP server with specified transport").option("-t, --type <type>", "Transport type: stdio", "stdio").option("--theme-path <path>", "Theme CSS file path relative to workspace root for get-css-classes when app config does not define style-system.themePath").option("--dev", "Start Vite dev server for component hot reload and caching").option("--app-path <path>", "App path for dev server (e.g., apps/agiflow-app)").action(async (options) => {
|
|
312
|
+
try {
|
|
313
|
+
const transportType = options.type.toLowerCase();
|
|
314
|
+
let devServerPort;
|
|
315
|
+
const bundlerService = await require_stdio.getBundlerServiceFromConfig();
|
|
316
|
+
if (options.dev) {
|
|
317
|
+
if (!options.appPath) {
|
|
318
|
+
console.error("Error: --app-path is required when using --dev flag");
|
|
319
|
+
console.error(`Example: ${require_stdio.STYLE_SYSTEM_CLI_NAME} mcp-serve --dev --app-path apps/agiflow-app`);
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
const { url, port } = await bundlerService.startDevServer(options.appPath);
|
|
323
|
+
devServerPort = port;
|
|
324
|
+
console.error(`Dev server started at ${url} (port: ${port})`);
|
|
325
|
+
}
|
|
326
|
+
if (transportType === "stdio") {
|
|
327
|
+
const container = require_stdio.createContainer({ defaultThemePath: options.themePath });
|
|
328
|
+
const server = require_stdio.createServer(container);
|
|
329
|
+
await startServer(new require_stdio.StdioTransportHandler(server), bundlerService, devServerPort);
|
|
330
|
+
} else {
|
|
331
|
+
console.error(`Unknown transport type: ${transportType}. Use: stdio`);
|
|
332
|
+
process.exit(1);
|
|
333
|
+
}
|
|
334
|
+
} catch (error) {
|
|
335
|
+
console.error("Failed to start MCP server:", error);
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/commands/polish-component.ts
|
|
341
|
+
/**
|
|
342
|
+
* Polish Component Command
|
|
343
|
+
*
|
|
344
|
+
* DESIGN PATTERNS:
|
|
345
|
+
* - Command pattern with Commander for CLI argument parsing
|
|
346
|
+
* - Async/await pattern for asynchronous operations
|
|
347
|
+
* - Error handling pattern with try-catch and proper exit codes
|
|
348
|
+
*
|
|
349
|
+
* CODING STANDARDS:
|
|
350
|
+
* - Use async action handlers for asynchronous operations
|
|
351
|
+
* - Handle errors gracefully with process.exit()
|
|
352
|
+
*
|
|
353
|
+
* AVOID:
|
|
354
|
+
* - Synchronous blocking operations in action handlers
|
|
355
|
+
* - Missing error handling (always use try-catch)
|
|
356
|
+
* - Hardcoded values (use options or environment variables)
|
|
357
|
+
*/
|
|
358
|
+
const polishComponentCommand = new commander.Command("polish-component").description("Polish a UI component using Antigravity with design system context").argument("<file>", "Path to the component .tsx file to polish").option("-i, --instructions <text>", "Specific polishing instructions (e.g., \"improve spacing\")").action(async (file, options) => {
|
|
359
|
+
try {
|
|
360
|
+
const result = await require_stdio.createContainer().get(require_stdio.STYLE_SYSTEM_TYPES.PolishComponentTool).execute({
|
|
361
|
+
filePath: file,
|
|
362
|
+
instructions: options.instructions
|
|
363
|
+
});
|
|
364
|
+
if (result.isError) {
|
|
365
|
+
const firstContent = result.content[0];
|
|
366
|
+
const errorText = firstContent?.type === "text" ? firstContent.text : "Unknown error";
|
|
367
|
+
throw new Error(errorText);
|
|
368
|
+
}
|
|
369
|
+
for (const content of result.content) if (content.type === "text") console.error(content.text);
|
|
370
|
+
} catch (error) {
|
|
371
|
+
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/cli.ts
|
|
377
|
+
/**
|
|
378
|
+
* MCP Server CLI Entry Point
|
|
379
|
+
*
|
|
380
|
+
* DESIGN PATTERNS:
|
|
381
|
+
* - CLI pattern with Commander for argument parsing
|
|
382
|
+
* - Command pattern for organizing CLI commands
|
|
383
|
+
* - Transport abstraction for multiple communication methods
|
|
384
|
+
*
|
|
385
|
+
* CODING STANDARDS:
|
|
386
|
+
* - Use async/await for asynchronous operations
|
|
387
|
+
* - Handle errors gracefully with try-catch
|
|
388
|
+
* - Log important events for debugging
|
|
389
|
+
* - Register all commands in main entry point
|
|
390
|
+
*
|
|
391
|
+
* AVOID:
|
|
392
|
+
* - Hardcoding command logic in index.ts (use separate command files)
|
|
393
|
+
* - Missing error handling for command execution
|
|
394
|
+
*/
|
|
395
|
+
/**
|
|
396
|
+
* Main entry point
|
|
397
|
+
*/
|
|
398
|
+
async function main() {
|
|
399
|
+
const program = new commander.Command();
|
|
400
|
+
program.name(require_stdio.STYLE_SYSTEM_CLI_NAME).description("MCP server for design system tools").version(require_stdio.STYLE_SYSTEM_VERSION);
|
|
401
|
+
program.addCommand(generateOxlintConfigCommand);
|
|
402
|
+
program.addCommand(getCSSClassesCommand);
|
|
403
|
+
program.addCommand(getUiComponentCommand);
|
|
404
|
+
program.addCommand(listAppComponentsCommand);
|
|
405
|
+
program.addCommand(listThemesCommand);
|
|
406
|
+
program.addCommand(listSharedComponentsCommand);
|
|
407
|
+
program.addCommand(mcpServeCommand);
|
|
408
|
+
program.addCommand(polishComponentCommand);
|
|
409
|
+
await program.parseAsync(process.argv);
|
|
410
|
+
}
|
|
411
|
+
main();
|
|
412
|
+
//#endregion
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "reflect-metadata";
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "reflect-metadata";
|