ebade 0.4.5 ā 0.4.7
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/.agent/workflows/prompt-to-product.md +36 -0
- package/ARCHITECTURE.md +17 -5
- package/CHANGELOG.md +32 -0
- package/MANIFESTO.md +25 -8
- package/README.md +63 -27
- package/assets/build-demo.gif +0 -0
- package/assets/build-demo.mp4 +0 -0
- package/cli/adapters/base.js +38 -0
- package/cli/adapters/html-vanilla.js +73 -0
- package/cli/adapters/nextjs.js +368 -0
- package/cli/scaffold.js +237 -1195
- package/cli/utils.js +98 -0
- package/docs/GREEN-AI.md +3 -3
- package/package.json +4 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/index.ts +41 -2
- package/packages/mcp-server/src/tools/build.ts +57 -0
- package/tests/cli/build.test.js +66 -0
- package/tests/cli/multi-target.test.js +60 -0
- package/tests/framework/architect.test.js +102 -0
- package/vhs/build-demo.tape +54 -0
- package/{demo.tape ā vhs/demo.tape} +3 -3
- package/www/app/page.tsx +1 -1
- package/www/package.json +1 -1
- package/www/public/assets/build-demo.gif +0 -0
- package/www/public/assets/build-demo.mp4 +0 -0
package/cli/utils.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
export function toPascalCase(str) {
|
|
4
|
+
return str
|
|
5
|
+
.split(/[-_]/)
|
|
6
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
7
|
+
.join("");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function toSnakeCase(str) {
|
|
11
|
+
return str
|
|
12
|
+
.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)
|
|
13
|
+
.replace(/-/g, "_")
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/^_/, "");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function hexToHsl(hex) {
|
|
19
|
+
let r = 0,
|
|
20
|
+
g = 0,
|
|
21
|
+
b = 0;
|
|
22
|
+
if (hex.length === 4) {
|
|
23
|
+
r = parseInt(hex[1] + hex[1], 16);
|
|
24
|
+
g = parseInt(hex[2] + hex[2], 16);
|
|
25
|
+
b = parseInt(hex[3] + hex[3], 16);
|
|
26
|
+
} else if (hex.length === 7) {
|
|
27
|
+
r = parseInt(hex.slice(1, 3), 16);
|
|
28
|
+
g = parseInt(hex.slice(3, 5), 16);
|
|
29
|
+
b = parseInt(hex.slice(5, 7), 16);
|
|
30
|
+
}
|
|
31
|
+
r /= 255;
|
|
32
|
+
g /= 255;
|
|
33
|
+
b /= 255;
|
|
34
|
+
let max = Math.max(r, g, b),
|
|
35
|
+
min = Math.min(r, g, b);
|
|
36
|
+
let h,
|
|
37
|
+
s,
|
|
38
|
+
l = (max + min) / 2;
|
|
39
|
+
if (max === min) h = s = 0;
|
|
40
|
+
else {
|
|
41
|
+
let d = max - min;
|
|
42
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
43
|
+
switch (max) {
|
|
44
|
+
case r:
|
|
45
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
46
|
+
break;
|
|
47
|
+
case g:
|
|
48
|
+
h = (b - r) / d + 2;
|
|
49
|
+
break;
|
|
50
|
+
case b:
|
|
51
|
+
h = (r - g) / d + 4;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
h /= 6;
|
|
55
|
+
}
|
|
56
|
+
return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(
|
|
57
|
+
l * 100
|
|
58
|
+
)}%`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function mapToSqlType(type) {
|
|
62
|
+
const typeMap = {
|
|
63
|
+
uuid: "UUID PRIMARY KEY DEFAULT gen_random_uuid()",
|
|
64
|
+
string: "VARCHAR(255)",
|
|
65
|
+
text: "TEXT",
|
|
66
|
+
integer: "INTEGER",
|
|
67
|
+
decimal: "DECIMAL(10,2)",
|
|
68
|
+
boolean: "BOOLEAN",
|
|
69
|
+
timestamp: "TIMESTAMP WITH TIME ZONE DEFAULT NOW()",
|
|
70
|
+
json: "JSONB",
|
|
71
|
+
array: "JSONB",
|
|
72
|
+
enum: "VARCHAR(50)",
|
|
73
|
+
};
|
|
74
|
+
return typeMap[type] || "VARCHAR(255)";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function ensureDir(dir) {
|
|
78
|
+
if (!fs.existsSync(dir)) {
|
|
79
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
import { execSync } from "child_process";
|
|
84
|
+
|
|
85
|
+
export function formatProject(projectDir) {
|
|
86
|
+
try {
|
|
87
|
+
// Try to use local prettier if it exists, otherwise npx
|
|
88
|
+
execSync(
|
|
89
|
+
`npx prettier --write "${projectDir}/**/*.{ts,tsx,js,jsx,html,css,json,yaml,md}" --ignore-path .gitignore`,
|
|
90
|
+
{
|
|
91
|
+
stdio: "ignore",
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
return true;
|
|
95
|
+
} catch (e) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
package/docs/GREEN-AI.md
CHANGED
|
@@ -41,11 +41,11 @@ Based on our benchmarks, switching to **ebade** for AI agent workflows saves:
|
|
|
41
41
|
|
|
42
42
|
## š§ The Efficiency Philosophy
|
|
43
43
|
|
|
44
|
-
Traditional frameworks are human-centric. They require the AI to write huge amounts of "how" code (boilerplate, imports, setup). **ebade**
|
|
44
|
+
Traditional frameworks are human-centric. They require the AI to write huge amounts of "how" code (boilerplate, imports, setup). **ebade** uses a hybrid approach to eliminate this waste.
|
|
45
45
|
|
|
46
46
|
```text
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
1. Offline Architect (Local): 0 Tokens ā Handles all boilerplate & structure.
|
|
48
|
+
2. Online Engineer (Agent): Low Tokens ā Handles only specific business logic.
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
**Same result. Fraction of the energy.**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ebade",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "ebade - Agent-First Framework. The first framework designed for AI agents, readable by humans.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "cli/scaffold.js",
|
|
@@ -42,5 +42,8 @@
|
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"prettier": "^3.7.4"
|
|
45
48
|
}
|
|
46
49
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ebade-mcp-server",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "MCP Server for ebade v0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
|
+
"description": "MCP Server for ebade v0.4.7 - The Agent-First Framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* - Validate ebade files
|
|
10
10
|
* - Compile ebade to framework-specific code
|
|
11
11
|
* - Generate components from natural language descriptions
|
|
12
|
+
* - Build entire projects from natural language prompts (NEW in v0.4.7)
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -24,12 +25,13 @@ import { scaffoldProject } from "./tools/scaffold.js";
|
|
|
24
25
|
import { validateIntent } from "./tools/validate.js";
|
|
25
26
|
import { compileIntent } from "./tools/compile.js";
|
|
26
27
|
import { generateComponent } from "./tools/generate.js";
|
|
28
|
+
import { buildFromPrompt } from "./tools/build.js";
|
|
27
29
|
|
|
28
30
|
// Create the MCP server
|
|
29
31
|
const server = new Server(
|
|
30
32
|
{
|
|
31
33
|
name: "ebade",
|
|
32
|
-
version: "0.
|
|
34
|
+
version: "0.4.7",
|
|
33
35
|
},
|
|
34
36
|
{
|
|
35
37
|
capabilities: {
|
|
@@ -183,6 +185,33 @@ Use this when:
|
|
|
183
185
|
required: ["description"],
|
|
184
186
|
},
|
|
185
187
|
},
|
|
188
|
+
{
|
|
189
|
+
name: "ebade_build",
|
|
190
|
+
description: `Revolutionary "Prompt-to-Product" tool.
|
|
191
|
+
Generates a complete, production-ready project from a single natural language description.
|
|
192
|
+
|
|
193
|
+
Use this when the user says:
|
|
194
|
+
- "Bana mor temalı bir kripto borsası yap"
|
|
195
|
+
- "Create a red themed SaaS for AI model store"
|
|
196
|
+
- "Make a sleek portfolio for a creative director"
|
|
197
|
+
|
|
198
|
+
This tool handles architecture, component selection, color palette, and scaffolding in one shot.`,
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: "object",
|
|
201
|
+
properties: {
|
|
202
|
+
prompt: {
|
|
203
|
+
type: "string",
|
|
204
|
+
description: "The natural language instruction for the project",
|
|
205
|
+
},
|
|
206
|
+
outputDir: {
|
|
207
|
+
type: "string",
|
|
208
|
+
description:
|
|
209
|
+
"Base directory path where the project will be created (absolute)",
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
required: ["prompt", "outputDir"],
|
|
213
|
+
},
|
|
214
|
+
},
|
|
186
215
|
],
|
|
187
216
|
};
|
|
188
217
|
});
|
|
@@ -229,6 +258,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
229
258
|
style: args?.style as any,
|
|
230
259
|
});
|
|
231
260
|
|
|
261
|
+
case "ebade_build":
|
|
262
|
+
return {
|
|
263
|
+
content: [
|
|
264
|
+
{
|
|
265
|
+
type: "text",
|
|
266
|
+
text: await buildFromPrompt(args as any),
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
};
|
|
270
|
+
|
|
232
271
|
default:
|
|
233
272
|
throw new Error(`Unknown tool: ${name}`);
|
|
234
273
|
}
|
|
@@ -278,7 +317,7 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
278
317
|
const { uri } = request.params;
|
|
279
318
|
|
|
280
319
|
const resources: Record<string, string> = {
|
|
281
|
-
"ebade://syntax": `# ebade Syntax Reference
|
|
320
|
+
"ebade://syntax": `# ebade Syntax Reference\n\n@page, @ebade, @requires, @outcomes, @data, @validate, @style, @compose, @on, @expects\n\nCode = f(ebade)`,
|
|
282
321
|
"ebade://examples/ecommerce": `# E-commerce ebade\nname: my-store\ntype: e-commerce\nfeatures:\n - product-catalog\n - shopping-cart\n - checkout`,
|
|
283
322
|
"ebade://examples/saas": `# SaaS ebade\nname: my-saas\ntype: saas-dashboard\nfeatures:\n - user-auth\n - billing\n - analytics`,
|
|
284
323
|
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
|
|
5
|
+
interface BuildArgs {
|
|
6
|
+
prompt: string;
|
|
7
|
+
outputDir: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function buildFromPrompt(args: BuildArgs): Promise<string> {
|
|
11
|
+
const { prompt, outputDir } = args;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// Find the CLI script path
|
|
15
|
+
// Assuming we are in packages/mcp-server/dist/tools/ (at runtime)
|
|
16
|
+
// or packages/mcp-server/src/tools/ (at dev time)
|
|
17
|
+
const cliPath = path.resolve(process.cwd(), "../../cli/scaffold.js");
|
|
18
|
+
|
|
19
|
+
if (!fs.existsSync(cliPath)) {
|
|
20
|
+
throw new Error(`CLI not found at ${cliPath}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log(`š Executing ebade build from prompt: "${prompt}"`);
|
|
24
|
+
|
|
25
|
+
// Execute the CLI command
|
|
26
|
+
// We pass the prompt as an argument.
|
|
27
|
+
// We need to handle the outputDir carefully.
|
|
28
|
+
// The CLI build command currently uses its own naming logic,
|
|
29
|
+
// but it creates the folder in the current process.cwd().
|
|
30
|
+
|
|
31
|
+
const cmd = `node "${cliPath}" build "${prompt}"`;
|
|
32
|
+
|
|
33
|
+
// Run in the specified outputDir if provided
|
|
34
|
+
const result = execSync(cmd, {
|
|
35
|
+
cwd: outputDir,
|
|
36
|
+
encoding: "utf-8",
|
|
37
|
+
env: { ...process.env, NODE_ENV: "production" },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return `ā
ebade v0.4.7 Build Complete!
|
|
41
|
+
|
|
42
|
+
Prompt: "${prompt}"
|
|
43
|
+
Output: ${outputDir}
|
|
44
|
+
|
|
45
|
+
CLI Output:
|
|
46
|
+
${result}
|
|
47
|
+
|
|
48
|
+
Next Steps:
|
|
49
|
+
1. Navigate to the generated folder.
|
|
50
|
+
2. Run 'npm install && npm run dev'.
|
|
51
|
+
3. Enjoy your turnkey project!`;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Build failed: ${error instanceof Error ? error.message : String(error)}`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import assert from "assert";
|
|
5
|
+
|
|
6
|
+
async function runCliTests() {
|
|
7
|
+
console.log("š§Ŗ Running CLI Integration Tests...\n");
|
|
8
|
+
|
|
9
|
+
const PROJECT_NAME = "ModernBlog";
|
|
10
|
+
if (fs.existsSync(PROJECT_NAME)) {
|
|
11
|
+
fs.rmSync(PROJECT_NAME, { recursive: true, force: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
// 1. Test 'ebade build' command
|
|
16
|
+
console.log(`Testing 'ebade build' command for ${PROJECT_NAME}...`);
|
|
17
|
+
const cmd = `node cli/scaffold.js build "A Modern Blog with blue theme"`;
|
|
18
|
+
|
|
19
|
+
execSync(cmd, { stdio: "inherit" });
|
|
20
|
+
|
|
21
|
+
const projectDir = path.join(process.cwd(), PROJECT_NAME);
|
|
22
|
+
|
|
23
|
+
assert.ok(
|
|
24
|
+
fs.existsSync(projectDir),
|
|
25
|
+
`Project directory (${PROJECT_NAME}) should exist`
|
|
26
|
+
);
|
|
27
|
+
assert.ok(
|
|
28
|
+
fs.existsSync(path.join(projectDir, "project.ebade.yaml")),
|
|
29
|
+
"project.ebade.yaml should be generated"
|
|
30
|
+
);
|
|
31
|
+
assert.ok(
|
|
32
|
+
fs.existsSync(path.join(projectDir, "app/page.tsx")),
|
|
33
|
+
"Main page should be generated"
|
|
34
|
+
);
|
|
35
|
+
assert.ok(
|
|
36
|
+
fs.existsSync(path.join(projectDir, ".env.example")),
|
|
37
|
+
".env.example should be generated"
|
|
38
|
+
);
|
|
39
|
+
assert.ok(
|
|
40
|
+
fs.existsSync(path.join(projectDir, ".gitignore")),
|
|
41
|
+
".gitignore should be generated"
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// Verify blog pages
|
|
45
|
+
assert.ok(
|
|
46
|
+
fs.existsSync(path.join(projectDir, "app/posts/page.tsx")),
|
|
47
|
+
"Blog index page should be generated"
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
console.log("ā
'ebade build' Integration OK");
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.error("\nā CLI Test failed:");
|
|
53
|
+
console.error(err);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
} finally {
|
|
56
|
+
// Cleanup
|
|
57
|
+
console.log("\nš§¹ Cleaning up test artifacts...");
|
|
58
|
+
if (fs.existsSync(PROJECT_NAME)) {
|
|
59
|
+
fs.rmSync(PROJECT_NAME, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log("\n⨠CLI integration tests passed!");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
runCliTests();
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import assert from "assert";
|
|
5
|
+
|
|
6
|
+
async function runMultiTargetTests() {
|
|
7
|
+
console.log("š§Ŗ Running Multi-Target TDD Tests...\n");
|
|
8
|
+
|
|
9
|
+
const PROJECT_NAME = "SimpleStatic";
|
|
10
|
+
if (fs.existsSync(PROJECT_NAME)) {
|
|
11
|
+
fs.rmSync(PROJECT_NAME, { recursive: true, force: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
// 1. Test 'ebade build' with --target html
|
|
16
|
+
console.log(`Testing '--target html' for ${PROJECT_NAME}...`);
|
|
17
|
+
// Note: This will fail initially because --target flag and adapter aren't implemented yet.
|
|
18
|
+
// This is the 'RED' phase of TDD.
|
|
19
|
+
const cmd = `node cli/scaffold.js build "A simple static site" --target html`;
|
|
20
|
+
|
|
21
|
+
execSync(cmd, { stdio: "inherit" });
|
|
22
|
+
|
|
23
|
+
const projectDir = path.join(process.cwd(), PROJECT_NAME);
|
|
24
|
+
|
|
25
|
+
assert.ok(
|
|
26
|
+
fs.existsSync(projectDir),
|
|
27
|
+
`Project directory (${PROJECT_NAME}) should exist`
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Vanilla HTML expected files
|
|
31
|
+
assert.ok(
|
|
32
|
+
fs.existsSync(path.join(projectDir, "index.html")),
|
|
33
|
+
"index.html should be generated for HTML target"
|
|
34
|
+
);
|
|
35
|
+
assert.ok(
|
|
36
|
+
fs.existsSync(path.join(projectDir, "styles.css")),
|
|
37
|
+
"styles.css should be generated for HTML target"
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Ensure Next.js files are NOT generated
|
|
41
|
+
assert.ok(
|
|
42
|
+
!fs.existsSync(path.join(projectDir, "app/page.tsx")),
|
|
43
|
+
"Next.js app directory should NOT exist for HTML target"
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
console.log("ā
Multi-Target TDD Test OK");
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.log("\nā TDD Test failed (Expected if not implemented yet):");
|
|
49
|
+
console.error(err.message);
|
|
50
|
+
// In TDD 'Red' phase, we don't necessarily exit(1) if we expect failure,
|
|
51
|
+
// but here we want to see it fail.
|
|
52
|
+
} finally {
|
|
53
|
+
// Cleanup
|
|
54
|
+
if (fs.existsSync(PROJECT_NAME)) {
|
|
55
|
+
fs.rmSync(PROJECT_NAME, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
runMultiTargetTests();
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EbadeArchitect,
|
|
3
|
+
toPascalCase,
|
|
4
|
+
toSnakeCase,
|
|
5
|
+
hexToHsl,
|
|
6
|
+
} from "../../cli/scaffold.js";
|
|
7
|
+
import assert from "assert";
|
|
8
|
+
|
|
9
|
+
async function runTests() {
|
|
10
|
+
console.log("š§Ŗ Running Framework Unit Tests (v0.4.7)...\n");
|
|
11
|
+
|
|
12
|
+
// 1. Utility Functions
|
|
13
|
+
console.log("Testing Utility Functions...");
|
|
14
|
+
assert.strictEqual(toPascalCase("hello-world"), "HelloWorld");
|
|
15
|
+
assert.strictEqual(toPascalCase("hello_world"), "HelloWorld");
|
|
16
|
+
assert.strictEqual(toSnakeCase("HelloWorld"), "hello_world");
|
|
17
|
+
assert.strictEqual(toSnakeCase("hello-world"), "hello_world");
|
|
18
|
+
|
|
19
|
+
// hexToHsl Test (Critical for Design System)
|
|
20
|
+
const hsl = hexToHsl("#8b5cf6"); // Violet
|
|
21
|
+
assert.ok(
|
|
22
|
+
hsl.includes("258"),
|
|
23
|
+
`HSL for #8b5cf6 should include hue 258, got ${hsl}`
|
|
24
|
+
);
|
|
25
|
+
console.log("ā
Utilities OK");
|
|
26
|
+
|
|
27
|
+
// 2. Architect Mapping
|
|
28
|
+
console.log("\nTesting EbadeArchitect (Complex Intent)...");
|
|
29
|
+
const prompt =
|
|
30
|
+
"Can you make a luxury gold themed dashboard with charts and login features?";
|
|
31
|
+
const config = await EbadeArchitect.plan(prompt);
|
|
32
|
+
|
|
33
|
+
// Check intelligence
|
|
34
|
+
assert.strictEqual(
|
|
35
|
+
config.name,
|
|
36
|
+
"LuxuryGold",
|
|
37
|
+
"Should filter filler words like 'Can you make a'"
|
|
38
|
+
);
|
|
39
|
+
assert.strictEqual(
|
|
40
|
+
config.design.colors.primary,
|
|
41
|
+
"#fbbf24",
|
|
42
|
+
"Gold detection failed"
|
|
43
|
+
);
|
|
44
|
+
assert.ok(
|
|
45
|
+
config.features.includes("Advanced Analytics"),
|
|
46
|
+
"Analytics detection failed"
|
|
47
|
+
);
|
|
48
|
+
assert.ok(
|
|
49
|
+
config.features.includes("Authentication"),
|
|
50
|
+
"Auth detection failed"
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Check Type-Aware Pages
|
|
54
|
+
assert.strictEqual(
|
|
55
|
+
config.pages.length,
|
|
56
|
+
2,
|
|
57
|
+
"Should have landing and dashboard"
|
|
58
|
+
);
|
|
59
|
+
assert.ok(
|
|
60
|
+
config.pages.some((p) => p.path === "/dashboard"),
|
|
61
|
+
"Dashboard page missing"
|
|
62
|
+
);
|
|
63
|
+
console.log("ā
Complex Intent mapping OK");
|
|
64
|
+
|
|
65
|
+
// 3. Project Type Specifics (E-commerce)
|
|
66
|
+
console.log("\nTesting EbadeArchitect (E-commerce)...");
|
|
67
|
+
const shopConfig = await EbadeArchitect.plan(
|
|
68
|
+
"Sleek shoe store with red theme"
|
|
69
|
+
);
|
|
70
|
+
assert.strictEqual(shopConfig.type, "e-commerce");
|
|
71
|
+
assert.ok(
|
|
72
|
+
shopConfig.pages.some((p) => p.path === "/products"),
|
|
73
|
+
"E-commerce missing /products"
|
|
74
|
+
);
|
|
75
|
+
assert.ok(
|
|
76
|
+
shopConfig.pages.some((p) => p.path === "/cart"),
|
|
77
|
+
"E-commerce missing /cart"
|
|
78
|
+
);
|
|
79
|
+
console.log("ā
E-commerce structure OK");
|
|
80
|
+
|
|
81
|
+
// 4. Project Type Specifics (Blog)
|
|
82
|
+
console.log("\nTesting EbadeArchitect (Blog)...");
|
|
83
|
+
const blogConfig = await EbadeArchitect.plan("Ocean themed news blog");
|
|
84
|
+
assert.strictEqual(blogConfig.type, "blog");
|
|
85
|
+
assert.ok(
|
|
86
|
+
blogConfig.pages.some((p) => p.path === "/posts"),
|
|
87
|
+
"Blog missing /posts index"
|
|
88
|
+
);
|
|
89
|
+
assert.ok(
|
|
90
|
+
blogConfig.pages.some((p) => p.path === "/posts/[slug]"),
|
|
91
|
+
"Blog missing /posts/[slug] dynamic route"
|
|
92
|
+
);
|
|
93
|
+
console.log("ā
Blog structure OK");
|
|
94
|
+
|
|
95
|
+
console.log("\n⨠All framework tests passed!");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
runTests().catch((err) => {
|
|
99
|
+
console.error("\nā Test failed:");
|
|
100
|
+
console.error(err);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# ebade v0.4.7 Build Demo
|
|
2
|
+
# Run with: vhs vhs/build-demo.tape
|
|
3
|
+
|
|
4
|
+
Output ../assets/build-demo.gif
|
|
5
|
+
Output ../assets/build-demo.mp4
|
|
6
|
+
|
|
7
|
+
Set FontSize 20
|
|
8
|
+
Set Width 1200
|
|
9
|
+
Set Height 800
|
|
10
|
+
Set Theme "Catppuccin Mocha"
|
|
11
|
+
Set Padding 40
|
|
12
|
+
Set TypingSpeed 60ms
|
|
13
|
+
|
|
14
|
+
# Start fresh
|
|
15
|
+
Hide
|
|
16
|
+
Type "rm -rf LuxuryConcierge"
|
|
17
|
+
Enter
|
|
18
|
+
Type "clear"
|
|
19
|
+
Enter
|
|
20
|
+
Sleep 500ms
|
|
21
|
+
Show
|
|
22
|
+
|
|
23
|
+
# Step 1: The Prompt
|
|
24
|
+
Type "# š”ļø Phase I: The Offline Architect"
|
|
25
|
+
Enter
|
|
26
|
+
Sleep 1s
|
|
27
|
+
Type "# Designing a project with 0 tokens using NPX..."
|
|
28
|
+
Enter
|
|
29
|
+
Sleep 1.5s
|
|
30
|
+
|
|
31
|
+
# The magic command using npx
|
|
32
|
+
Type "npx ebade build 'A luxury concierge service with pricing, testimonials and a gold theme'"
|
|
33
|
+
Sleep 500ms
|
|
34
|
+
Enter
|
|
35
|
+
|
|
36
|
+
# Wait for the Architect to work (Creative Brief output)
|
|
37
|
+
Sleep 15s
|
|
38
|
+
|
|
39
|
+
# Step 2: Show the result
|
|
40
|
+
Type "# ā
Project designed and scaffolded in seconds."
|
|
41
|
+
Enter
|
|
42
|
+
Sleep 1.5s
|
|
43
|
+
Type "ls -R LuxuryConcierge/app"
|
|
44
|
+
Enter
|
|
45
|
+
Sleep 4s
|
|
46
|
+
|
|
47
|
+
# Final tagline
|
|
48
|
+
Type "# š ebade: Hybrid Workflow."
|
|
49
|
+
Enter
|
|
50
|
+
Sleep 1s
|
|
51
|
+
Type "# ā Get started at ebade.dev"
|
|
52
|
+
Enter
|
|
53
|
+
|
|
54
|
+
Sleep 4s
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# ebade Demo Video Script
|
|
2
|
-
# Run with: vhs demo.tape
|
|
2
|
+
# Run with: vhs vhs/demo.tape
|
|
3
3
|
# Outputs: demo.gif + demo.mp4
|
|
4
4
|
|
|
5
5
|
# Outputs - both formats
|
|
6
|
-
Output assets/demo.gif
|
|
7
|
-
Output assets/demo.mp4
|
|
6
|
+
Output ../assets/demo.gif
|
|
7
|
+
Output ../assets/demo.mp4
|
|
8
8
|
|
|
9
9
|
# Configuration
|
|
10
10
|
Set FontSize 20
|
package/www/app/page.tsx
CHANGED
|
@@ -67,7 +67,7 @@ export default function HomePage() {
|
|
|
67
67
|
<div className="visual-glow"></div>
|
|
68
68
|
<div className="video-container">
|
|
69
69
|
<video className="hero-video" autoPlay loop muted playsInline>
|
|
70
|
-
<source src="/assets/demo.mp4" type="video/mp4" />
|
|
70
|
+
<source src="/assets/build-demo.mp4" type="video/mp4" />
|
|
71
71
|
</video>
|
|
72
72
|
</div>
|
|
73
73
|
</div>
|
package/www/package.json
CHANGED
|
Binary file
|
|
Binary file
|