aiesthetic-cli 1.0.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.
Files changed (3) hide show
  1. package/README.md +50 -0
  2. package/bin/cli.js +192 -0
  3. package/package.json +25 -0
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # aiesthetic-cli
2
+
3
+ The official Asset Engine for the AIesthetic platform. Generate and download high-quality visual assets (12s cinematic videos and 360 animation frames) directly to your local workspace.
4
+
5
+ ## Installation
6
+
7
+ You can run the CLI without installing it using `npx`:
8
+
9
+ ```bash
10
+ npx aiesthetic-cli "Design a luxury watch website" "cinematic"
11
+ ```
12
+
13
+ ## Setup
14
+
15
+ The CLI requires an API key to function. Create a `.env` file in your working directory:
16
+
17
+ ```env
18
+ AIESTHETIC_API_KEY=your_live_key_here
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ npx aiesthetic-cli <prompt> [style]
25
+ ```
26
+
27
+ - **prompt**: Descriptive text for your scene (e.g., "A futuristic flying car")
28
+ - **style**: (Optional) Visual style. Options: `cinematic` (default), `modern`, `bold`, etc.
29
+
30
+ ## Output
31
+
32
+ The CLI creates a structured directory:
33
+
34
+ ```text
35
+ aiesthetic_assets/
36
+ └── req_abc123/
37
+ ├── frames/ # 360 sequential frames (30fps)
38
+ ├── video.mp4 # 12s high-resolution video
39
+ ├── README.md # Implementation instructions
40
+ └── cursor-prompt.txt # Prompt for your AI coding agent
41
+ ```
42
+
43
+ ## Features
44
+
45
+ - **Multi-threaded Downloads**: Fast asset retrieval with parallel streams.
46
+ - **Zero-Config**: Works out of the box with `npx`.
47
+ - **AI Agent Ready**: Provides pre-formatted prompts for tools like Cursor and Windsurf.
48
+
49
+ ---
50
+ © 2024 AIesthetic Team. All rights reserved.
package/bin/cli.js ADDED
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const https = require('https');
6
+ const crypto = require('crypto');
7
+
8
+ // ─────────────────────────────────────────
9
+ // COLORS & UI UTILS
10
+ // ─────────────────────────────────────────
11
+ const color = {
12
+ reset: "\x1b[0m",
13
+ bold: "\x1b[1m",
14
+ cyan: "\x1b[36m",
15
+ green: "\x1b[32m",
16
+ yellow: "\x1b[33m",
17
+ red: "\x1b[31m",
18
+ dim: "\x1b[2m",
19
+ };
20
+
21
+ // ─────────────────────────────────────────
22
+ // ENV LOADER
23
+ // ─────────────────────────────────────────
24
+ function loadEnv() {
25
+ if (fs.existsSync('.env')) {
26
+ const envFile = fs.readFileSync('.env', 'utf-8');
27
+ envFile.split('\n').forEach(line => {
28
+ const parts = line.split('=');
29
+ if (parts.length >= 2) {
30
+ const key = parts[0].trim();
31
+ const value = parts.slice(1).join('=').trim().replace(/['"]/g, '');
32
+ process.env[key] = value;
33
+ }
34
+ });
35
+ }
36
+ }
37
+
38
+ loadEnv();
39
+
40
+ const CONFIG = {
41
+ BASE_URL: 'https://us-central1-aiestheticbackend.cloudfunctions.net/api/v1',
42
+ API_KEY: process.env.AIESTHETIC_API_KEY,
43
+ PROMPT: process.argv[2],
44
+ STYLE: process.argv[3] || 'cinematic',
45
+ CONCURRENT_DOWNLOADS: 10,
46
+ };
47
+
48
+ // ─────────────────────────────────────────
49
+ // CORE UTILS
50
+ // ─────────────────────────────────────────
51
+ async function request(method, path, body = null) {
52
+ return new Promise((resolve, reject) => {
53
+ const options = {
54
+ method,
55
+ hostname: 'us-central1-aiestheticbackend.cloudfunctions.net',
56
+ path: `/api${path}`,
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ 'x-api-key': CONFIG.API_KEY,
60
+ },
61
+ timeout: 900000,
62
+ };
63
+
64
+ const req = https.request(options, (res) => {
65
+ let data = '';
66
+ res.on('data', (chunk) => data += chunk);
67
+ res.on('end', () => {
68
+ try {
69
+ const parsed = JSON.parse(data);
70
+ if (res.statusCode >= 400) reject(parsed);
71
+ else resolve(parsed);
72
+ } catch (e) {
73
+ reject(new Error(`Failed to parse response: ${data}`));
74
+ }
75
+ });
76
+ });
77
+
78
+ req.on('error', reject);
79
+ if (body) req.write(JSON.stringify(body));
80
+ req.end();
81
+ });
82
+ }
83
+
84
+ function downloadFile(url, dest) {
85
+ return new Promise((resolve, reject) => {
86
+ const file = fs.createWriteStream(dest);
87
+ https.get(url, (res) => {
88
+ if (res.statusCode !== 200) {
89
+ reject(new Error(`Failed to download: ${res.statusCode}`));
90
+ return;
91
+ }
92
+ res.pipe(file);
93
+ file.on('finish', () => {
94
+ file.close();
95
+ resolve();
96
+ });
97
+ }).on('error', (err) => {
98
+ fs.unlink(dest, () => {});
99
+ reject(err);
100
+ });
101
+ });
102
+ }
103
+
104
+ // ─────────────────────────────────────────
105
+ // MAIN ENGINE
106
+ // ─────────────────────────────────────────
107
+ async function main() {
108
+ console.log(`\n${color.bold}${color.cyan}╔══════════════════════════════════════════════════════════╗${color.reset}`);
109
+ console.log(`${color.bold}${color.cyan}║ AIesthetic CLI — Asset Engine ║${color.reset}`);
110
+ console.log(`${color.bold}${color.cyan}╚══════════════════════════════════════════════════════════╝${color.reset}\n`);
111
+
112
+ if (!CONFIG.API_KEY) {
113
+ console.log(`${color.red}❌ Error: AIESTHETIC_API_KEY not found.${color.reset}`);
114
+ console.log(`${color.dim}Please add it to your .env file or export it as an environment variable.${color.reset}\n`);
115
+ process.exit(1);
116
+ }
117
+
118
+ if (!CONFIG.PROMPT) {
119
+ console.log(`${color.yellow}⚠️ Usage: npx aiesthetic "Your Prompt" "style"${color.reset}\n`);
120
+ process.exit(0);
121
+ }
122
+
123
+ try {
124
+ // 1. Check Credits
125
+ process.stdout.write(` ${color.dim}▶${color.reset} Verifying Account... `);
126
+ const creditInfo = await request('GET', '/v1/credits');
127
+ console.log(`${color.green}Balance: ${creditInfo.credits} credits${color.reset}`);
128
+
129
+ // 2. Generate
130
+ console.log(` ${color.dim}▶${color.reset} Generating Assets...`);
131
+ console.log(` ${color.dim}Prompt:${color.reset} "${CONFIG.PROMPT}"`);
132
+ console.log(` ${color.dim}Style: ${color.reset} ${CONFIG.STYLE}`);
133
+ console.log(` ${color.yellow}⏳ Processing through GPU cluster (2-5 mins)...${color.reset}`);
134
+
135
+ const startTime = Date.now();
136
+ const generation = await request('POST', '/v1/generate', {
137
+ prompt: CONFIG.PROMPT,
138
+ style: CONFIG.STYLE,
139
+ });
140
+
141
+ const duration = ((Date.now() - startTime) / 1000).toFixed(1);
142
+ console.log(` ${color.green}✓ Generation complete in ${duration}s${color.reset}\n`);
143
+
144
+ // 3. Download
145
+ const { assets, requestId } = generation;
146
+ const outputDir = path.join(process.cwd(), 'aiesthetic_assets', requestId);
147
+ const framesDir = path.join(outputDir, 'frames');
148
+
149
+ console.log(` ${color.dim}▶${color.reset} Downloading Assets...`);
150
+ console.log(` ${color.dim}Target:${color.reset} ${outputDir}`);
151
+
152
+ if (!fs.existsSync(framesDir)) fs.mkdirSync(framesDir, { recursive: true });
153
+
154
+ // Download Video
155
+ process.stdout.write(` ${color.dim}• Downloading video...${color.reset} `);
156
+ await downloadFile(assets.videoUrl, path.join(outputDir, 'video.mp4'));
157
+ console.log(`${color.green}done${color.reset}`);
158
+
159
+ // Download Frames (Parallel)
160
+ const frameUrls = assets.frames.urls;
161
+ process.stdout.write(` ${color.dim}• Downloading 360 frames...${color.reset} `);
162
+
163
+ for (let i = 0; i < frameUrls.length; i += CONFIG.CONCURRENT_DOWNLOADS) {
164
+ const chunk = frameUrls.slice(i, i + CONFIG.CONCURRENT_DOWNLOADS);
165
+ await Promise.all(chunk.map((url, idx) => {
166
+ const frameNum = (i + idx + 1).toString().padStart(4, '0');
167
+ return downloadFile(url, path.join(framesDir, `frame_${frameNum}.jpg`));
168
+ }));
169
+ const progress = Math.round(((i + chunk.length) / frameUrls.length) * 100);
170
+ process.stdout.write(`\r ${color.dim}• Downloading 360 frames...${color.reset} ${color.cyan}${progress}%${color.reset}`);
171
+ }
172
+ console.log(` ${color.green}complete${color.reset}`);
173
+
174
+ // Save Meta
175
+ fs.writeFileSync(path.join(outputDir, 'README.md'), assets.readme.markdown);
176
+ fs.writeFileSync(path.join(outputDir, 'cursor-prompt.txt'), assets.readme.cursorPrompt);
177
+
178
+ console.log(`\n ${color.bold}${color.green}✨ GENERATION SUCCESSFUL${color.reset}`);
179
+ console.log(` ${color.dim}══════════════════════════════════════════════════════${color.reset}`);
180
+ console.log(` ${color.bold} NEXT STEPS FOR YOUR AI AGENT:${color.reset}`);
181
+ console.log(` 1. Open the generated README: ${color.cyan}${path.join(outputDir, 'README.md')}${color.reset}`);
182
+ console.log(` 2. Follow the technical instructions to build the site.`);
183
+ console.log(` 3. The cursor-prompt.txt contains your ready-to-use system prompt.`);
184
+ console.log(` ${color.dim}══════════════════════════════════════════════════════${color.reset}\n`);
185
+
186
+ } catch (error) {
187
+ console.log(`\n${color.red}❌ Error:${color.reset}`, error.message || error.code || error);
188
+ process.exit(1);
189
+ }
190
+ }
191
+
192
+ main();
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "aiesthetic-cli",
3
+ "version": "1.0.0",
4
+ "description": "AIesthetic Asset Engine — Generate and download high-quality visual components from your terminal.",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "aiesthetic": "bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [
13
+ "ai",
14
+ "generative",
15
+ "vfx",
16
+ "web-design",
17
+ "cli",
18
+ "aiesthetic"
19
+ ],
20
+ "author": "AIesthetic Team",
21
+ "license": "MIT",
22
+ "dependencies": {
23
+ "dotenv": "^16.4.5"
24
+ }
25
+ }