keen-project-create 1.0.14 → 1.0.16
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/dist/index.mjs +164 -137
- package/package.json +34 -34
- package/readme.md +81 -81
- package/templates/default/keen.json +14 -8
- package/templates/default/package.json +16 -16
- package/templates/default/src/flows/Project.flow.json +5 -5
- package/templates/default/src/scripts/debux.js +5 -5
- package/templates/vscode/.prettierignore +6 -6
- package/templates/vscode/.prettierrc +10 -10
- package/templates/vscode/.vscode/launch.json +17 -17
- package/templates/vscode/.vscode/settings.json +7 -7
- package/templates/vscode/keen-tools.json +2 -2
- package/templates/vscode/keen.json +14 -8
- package/templates/vscode/package.json +17 -17
- package/templates/vscode/src/agents/Agent-__PROJECT_NAME_REPLACE__/00-system.md +1 -0
- package/templates/vscode/src/agents/Agent-__PROJECT_NAME_REPLACE__/settings.json +14 -0
- package/templates/vscode/src/flows/Project/instructions.json +35 -0
- package/templates/vscode/src/flows/Project/node-settings.json +4 -0
- package/templates/vscode/src/flows/Project/positions.json +22 -0
- package/templates/vscode/src/flows/Project.flow.json +87 -5
- package/templates/vscode/src/scripts/debux.js +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,137 +1,164 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import fsp from 'fs/promises';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
import { spawn } from 'child_process';
|
|
8
|
-
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
-
const __dirname = path.dirname(__filename);
|
|
11
|
-
|
|
12
|
-
const rawArgs = process.argv.slice(2);
|
|
13
|
-
|
|
14
|
-
// grab --type=... or --type ...
|
|
15
|
-
let typeFromFlag;
|
|
16
|
-
for (let i = 0; i < rawArgs.length; i++) {
|
|
17
|
-
if (rawArgs[i].startsWith('--type=')) {
|
|
18
|
-
typeFromFlag = rawArgs[i].split('=')[1];
|
|
19
|
-
break;
|
|
20
|
-
}
|
|
21
|
-
if (rawArgs[i] === '--type' && rawArgs[i + 1]) {
|
|
22
|
-
typeFromFlag = rawArgs[i + 1];
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const positional = rawArgs.filter(a => !a.startsWith('-'));
|
|
28
|
-
const projectNameArg = positional[0];
|
|
29
|
-
const positionalType = positional[1];
|
|
30
|
-
|
|
31
|
-
if (!projectNameArg) {
|
|
32
|
-
console.error('Usage: keen-project-create <project-name>');
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const projectType = (typeFromFlag || positionalType || '').toLowerCase();
|
|
37
|
-
|
|
38
|
-
// Resolve paths
|
|
39
|
-
const TEMPLATE_DEFAULT = path.resolve(__dirname, '../templates/default');
|
|
40
|
-
const TEMPLATE_VSCODE = path.resolve(__dirname, '../templates/vscode');
|
|
41
|
-
|
|
42
|
-
//const TEMPLATE_DIR = projectType === 'vscode' ? TEMPLATE_VSCODE : TEMPLATE_DEFAULT;
|
|
43
|
-
const TEMPLATE_DIR = TEMPLATE_VSCODE;
|
|
44
|
-
|
|
45
|
-
const targetDir = path.resolve(process.cwd(), projectNameArg);
|
|
46
|
-
|
|
47
|
-
async function ensureDirEmptyOrCreate(dir) {
|
|
48
|
-
try {
|
|
49
|
-
await fsp.mkdir(dir, { recursive: true });
|
|
50
|
-
const items = await fsp.readdir(dir);
|
|
51
|
-
if (items.length > 0) {
|
|
52
|
-
console.error(`Target directory is not empty: ${dir}`);
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
} catch (e) {
|
|
56
|
-
console.error('Failed creating target directory:', e);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function copyDir(src, dest) {
|
|
62
|
-
await fsp.mkdir(dest, { recursive: true });
|
|
63
|
-
const entries = await fsp.readdir(src, { withFileTypes: true });
|
|
64
|
-
for (const entry of entries) {
|
|
65
|
-
const s = path.join(src, entry.name);
|
|
66
|
-
const d = path.join(dest, entry.name);
|
|
67
|
-
if (entry.isDirectory()) {
|
|
68
|
-
await copyDir(s, d);
|
|
69
|
-
} else {
|
|
70
|
-
await fsp.copyFile(s, d);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function replaceInFile(filePath, replacements) {
|
|
76
|
-
const exists = fs.existsSync(filePath);
|
|
77
|
-
if (!exists) return;
|
|
78
|
-
let content = await fsp.readFile(filePath, 'utf-8');
|
|
79
|
-
for (const [from, to] of Object.entries(replacements)) {
|
|
80
|
-
content = content.replaceAll(from, to);
|
|
81
|
-
}
|
|
82
|
-
await fsp.writeFile(filePath, content);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Choose package manager: npm by default
|
|
86
|
-
function detectPackageManager() {
|
|
87
|
-
// You could enhance to check for pnpm/yarn existence.
|
|
88
|
-
return 'npm';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function runInstall(cwd, pm = 'npm') {
|
|
92
|
-
return new Promise((resolve, reject) => {
|
|
93
|
-
const args = ['install'];
|
|
94
|
-
const child = spawn(pm, args, { stdio: 'inherit', cwd, shell: process.platform === 'win32' });
|
|
95
|
-
child.on('close', code => (code === 0 ? resolve() : reject(new Error(pm + ' install failed'))));
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
(async () => {
|
|
100
|
-
console.log(`> Creating project: ${projectNameArg}`);
|
|
101
|
-
await ensureDirEmptyOrCreate(targetDir);
|
|
102
|
-
|
|
103
|
-
console.log('> Copying template…');
|
|
104
|
-
await copyDir(TEMPLATE_DIR, targetDir);
|
|
105
|
-
|
|
106
|
-
// Optional: personalize package.json
|
|
107
|
-
const pkgJsonPath = path.join(targetDir, 'package.json');
|
|
108
|
-
await replaceInFile(pkgJsonPath, {
|
|
109
|
-
__APP_NAME__: projectNameArg
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Apply props inside the "templates/vscode/launch.json" file
|
|
113
|
-
const launchFile = path.join(targetDir, '.vscode', 'launch.json');
|
|
114
|
-
await replaceInFile(launchFile, {
|
|
115
|
-
__PROJECT_NAME_REPLACE__ : projectNameArg
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Apply props inside the "templates/keen.json" file
|
|
119
|
-
const keenJsonFile = path.join(targetDir, 'keen.json');
|
|
120
|
-
await replaceInFile(keenJsonFile, {
|
|
121
|
-
__PROJECT_NAME_REPLACE__ : projectNameArg
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
//
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import fsp from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
|
|
12
|
+
const rawArgs = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
// grab --type=... or --type ...
|
|
15
|
+
let typeFromFlag;
|
|
16
|
+
for (let i = 0; i < rawArgs.length; i++) {
|
|
17
|
+
if (rawArgs[i].startsWith('--type=')) {
|
|
18
|
+
typeFromFlag = rawArgs[i].split('=')[1];
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
if (rawArgs[i] === '--type' && rawArgs[i + 1]) {
|
|
22
|
+
typeFromFlag = rawArgs[i + 1];
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const positional = rawArgs.filter(a => !a.startsWith('-'));
|
|
28
|
+
const projectNameArg = positional[0];
|
|
29
|
+
const positionalType = positional[1];
|
|
30
|
+
|
|
31
|
+
if (!projectNameArg) {
|
|
32
|
+
console.error('Usage: keen-project-create <project-name>');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const projectType = (typeFromFlag || positionalType || '').toLowerCase();
|
|
37
|
+
|
|
38
|
+
// Resolve paths
|
|
39
|
+
const TEMPLATE_DEFAULT = path.resolve(__dirname, '../templates/default');
|
|
40
|
+
const TEMPLATE_VSCODE = path.resolve(__dirname, '../templates/vscode');
|
|
41
|
+
|
|
42
|
+
//const TEMPLATE_DIR = projectType === 'vscode' ? TEMPLATE_VSCODE : TEMPLATE_DEFAULT;
|
|
43
|
+
const TEMPLATE_DIR = TEMPLATE_VSCODE;
|
|
44
|
+
|
|
45
|
+
const targetDir = path.resolve(process.cwd(), projectNameArg);
|
|
46
|
+
|
|
47
|
+
async function ensureDirEmptyOrCreate(dir) {
|
|
48
|
+
try {
|
|
49
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
50
|
+
const items = await fsp.readdir(dir);
|
|
51
|
+
if (items.length > 0) {
|
|
52
|
+
console.error(`Target directory is not empty: ${dir}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
console.error('Failed creating target directory:', e);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function copyDir(src, dest) {
|
|
62
|
+
await fsp.mkdir(dest, { recursive: true });
|
|
63
|
+
const entries = await fsp.readdir(src, { withFileTypes: true });
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
const s = path.join(src, entry.name);
|
|
66
|
+
const d = path.join(dest, entry.name);
|
|
67
|
+
if (entry.isDirectory()) {
|
|
68
|
+
await copyDir(s, d);
|
|
69
|
+
} else {
|
|
70
|
+
await fsp.copyFile(s, d);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function replaceInFile(filePath, replacements) {
|
|
76
|
+
const exists = fs.existsSync(filePath);
|
|
77
|
+
if (!exists) return;
|
|
78
|
+
let content = await fsp.readFile(filePath, 'utf-8');
|
|
79
|
+
for (const [from, to] of Object.entries(replacements)) {
|
|
80
|
+
content = content.replaceAll(from, to);
|
|
81
|
+
}
|
|
82
|
+
await fsp.writeFile(filePath, content);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Choose package manager: npm by default
|
|
86
|
+
function detectPackageManager() {
|
|
87
|
+
// You could enhance to check for pnpm/yarn existence.
|
|
88
|
+
return 'npm';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function runInstall(cwd, pm = 'npm') {
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
const args = ['install'];
|
|
94
|
+
const child = spawn(pm, args, { stdio: 'inherit', cwd, shell: process.platform === 'win32' });
|
|
95
|
+
child.on('close', code => (code === 0 ? resolve() : reject(new Error(pm + ' install failed'))));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
(async () => {
|
|
100
|
+
console.log(`> Creating project: ${projectNameArg}`);
|
|
101
|
+
await ensureDirEmptyOrCreate(targetDir);
|
|
102
|
+
|
|
103
|
+
console.log('> Copying template…');
|
|
104
|
+
await copyDir(TEMPLATE_DIR, targetDir);
|
|
105
|
+
|
|
106
|
+
// Optional: personalize package.json
|
|
107
|
+
const pkgJsonPath = path.join(targetDir, 'package.json');
|
|
108
|
+
await replaceInFile(pkgJsonPath, {
|
|
109
|
+
__APP_NAME__: projectNameArg
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Apply props inside the "templates/vscode/launch.json" file
|
|
113
|
+
const launchFile = path.join(targetDir, '.vscode', 'launch.json');
|
|
114
|
+
await replaceInFile(launchFile, {
|
|
115
|
+
__PROJECT_NAME_REPLACE__ : projectNameArg
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Apply props inside the "templates/keen.json" file
|
|
119
|
+
const keenJsonFile = path.join(targetDir, 'keen.json');
|
|
120
|
+
await replaceInFile(keenJsonFile, {
|
|
121
|
+
__PROJECT_NAME_REPLACE__ : projectNameArg
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Rename agent folder from template placeholder to actual project name
|
|
125
|
+
const agentTemplateName = 'Agent-__PROJECT_NAME_REPLACE__';
|
|
126
|
+
const agentActualName = `Agent-${projectNameArg}`;
|
|
127
|
+
const agentTemplateDir = path.join(targetDir, 'src', 'agents', agentTemplateName);
|
|
128
|
+
const agentActualDir = path.join(targetDir, 'src', 'agents', agentActualName);
|
|
129
|
+
if (fs.existsSync(agentTemplateDir)) {
|
|
130
|
+
await fsp.rename(agentTemplateDir, agentActualDir);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Apply props inside agent settings.json
|
|
134
|
+
const agentSettingsFile = path.join(agentActualDir, 'settings.json');
|
|
135
|
+
await replaceInFile(agentSettingsFile, {
|
|
136
|
+
__PROJECT_NAME_REPLACE__: projectNameArg
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Apply props inside flow instructions.json
|
|
140
|
+
const flowInstructionsFile = path.join(targetDir, 'src', 'flows', 'Project', 'instructions.json');
|
|
141
|
+
await replaceInFile(flowInstructionsFile, {
|
|
142
|
+
__PROJECT_NAME_REPLACE__: projectNameArg
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Apply props inside Project.flow.json (human viewport visualization)
|
|
146
|
+
const projectFlowFile = path.join(targetDir, 'src', 'flows', 'Project.flow.json');
|
|
147
|
+
await replaceInFile(projectFlowFile, {
|
|
148
|
+
__PROJECT_NAME_REPLACE__: projectNameArg
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Install deps
|
|
152
|
+
const pm = detectPackageManager();
|
|
153
|
+
console.log(`> Installing dependencies with ${pm}…`);
|
|
154
|
+
await runInstall(targetDir, pm);
|
|
155
|
+
|
|
156
|
+
console.log('\n✅ Done!');
|
|
157
|
+
console.log(`\nNext steps:
|
|
158
|
+
cd ${projectNameArg}
|
|
159
|
+
${pm} run dev
|
|
160
|
+
`);
|
|
161
|
+
})().catch(err => {
|
|
162
|
+
console.error(err);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
});
|
package/package.json
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "keen-project-create",
|
|
3
|
-
"description": "Project scaffolder for Keen projects",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"keen-project-create": "dist/index.mjs"
|
|
9
|
-
},
|
|
10
|
-
"repository": {
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/Keen-Agents/keen-project-create.git"
|
|
13
|
-
},
|
|
14
|
-
"files": [
|
|
15
|
-
"dist/",
|
|
16
|
-
"templates/",
|
|
17
|
-
"README.md",
|
|
18
|
-
"LICENSE"
|
|
19
|
-
],
|
|
20
|
-
"publishConfig": {
|
|
21
|
-
"access": "public",
|
|
22
|
-
"registry": "https://registry.npmjs.org/"
|
|
23
|
-
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
26
|
-
},
|
|
27
|
-
"keywords": [],
|
|
28
|
-
"author": "Paskal Novakov",
|
|
29
|
-
"license": "ISC",
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"husky": "^9.1.7",
|
|
32
|
-
"prettier": "^3.6.2"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "keen-project-create",
|
|
3
|
+
"description": "Project scaffolder for Keen projects",
|
|
4
|
+
"version": "1.0.16",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"keen-project-create": "dist/index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/Keen-Agents/keen-project-create.git"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"templates/",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"registry": "https://registry.npmjs.org/"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [],
|
|
28
|
+
"author": "Paskal Novakov",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"husky": "^9.1.7",
|
|
32
|
+
"prettier": "^3.6.2"
|
|
33
|
+
}
|
|
34
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
# KEEN PROJECT CREATE
|
|
2
|
-
|
|
3
|
-
> **KEEN PROJECT CREATE** is scaffold **Keen Agents Projects**.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🚀 Overview
|
|
8
|
-
|
|
9
|
-
This package is a NPX command that creates ready for use project setup.
|
|
10
|
-
It comes preconfigured with modern developer tools and practices:
|
|
11
|
-
|
|
12
|
-
- **Husky hooks** for Git workflow automation
|
|
13
|
-
- **Prettier** for code style and formatting
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
## 🌿 Usage
|
|
17
|
-
Standard template
|
|
18
|
-
```
|
|
19
|
-
npx keen-project-create <PROJECT_DIR>
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
VSCode template with prettrier and debugger
|
|
23
|
-
```
|
|
24
|
-
npx keen-project-create <PROJECT_DIR> vscode
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## 📝 Code Standards
|
|
30
|
-
|
|
31
|
-
We use **Prettier** to maintain consistent code style (spacing, formatting).
|
|
32
|
-
|
|
33
|
-
For the best experience:
|
|
34
|
-
|
|
35
|
-
- Install the Prettier VS Code plugin
|
|
36
|
-
- Make sure code is formatted before committing
|
|
37
|
-
|
|
38
|
-
## 🌿 Branching Strategy
|
|
39
|
-
|
|
40
|
-
Branch names must follow one of these formats:
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
- feature/KPC-<NUMBER>
|
|
44
|
-
- fix/KPC-<NUMBER>
|
|
45
|
-
- hotfix/KPC-<NUMBER>
|
|
46
|
-
- remove/KPC-<NUMBER>
|
|
47
|
-
- release/KPC-<NUMBER>
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Where `<NUMBER>` is the ticket number.
|
|
51
|
-
|
|
52
|
-
## 📝 Commit Messages
|
|
53
|
-
|
|
54
|
-
Each commit message must follow this format:
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
KPC-<NUMBER>:<ADD|FIX|DELETE>: <MESSAGE>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
NUMBER: Ticket number
|
|
62
|
-
|
|
63
|
-
ADD: A new feature
|
|
64
|
-
|
|
65
|
-
FIX: A feature was fixed
|
|
66
|
-
|
|
67
|
-
DELETE: Code cleaned or removed
|
|
68
|
-
|
|
69
|
-
MESSAGE: Short description of the change
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Example:
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
KPC-123:ADD: Version X.X.X
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## 🔀 Pull Requests
|
|
79
|
-
|
|
80
|
-
- After pushing, create a PR to the development branch
|
|
81
|
-
- A minimum of 2 reviewers must approve before merging
|
|
1
|
+
# KEEN PROJECT CREATE
|
|
2
|
+
|
|
3
|
+
> **KEEN PROJECT CREATE** is scaffold **Keen Agents Projects**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Overview
|
|
8
|
+
|
|
9
|
+
This package is a NPX command that creates ready for use project setup.
|
|
10
|
+
It comes preconfigured with modern developer tools and practices:
|
|
11
|
+
|
|
12
|
+
- **Husky hooks** for Git workflow automation
|
|
13
|
+
- **Prettier** for code style and formatting
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
## 🌿 Usage
|
|
17
|
+
Standard template
|
|
18
|
+
```
|
|
19
|
+
npx keen-project-create <PROJECT_DIR>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
VSCode template with prettrier and debugger
|
|
23
|
+
```
|
|
24
|
+
npx keen-project-create <PROJECT_DIR> vscode
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 📝 Code Standards
|
|
30
|
+
|
|
31
|
+
We use **Prettier** to maintain consistent code style (spacing, formatting).
|
|
32
|
+
|
|
33
|
+
For the best experience:
|
|
34
|
+
|
|
35
|
+
- Install the Prettier VS Code plugin
|
|
36
|
+
- Make sure code is formatted before committing
|
|
37
|
+
|
|
38
|
+
## 🌿 Branching Strategy
|
|
39
|
+
|
|
40
|
+
Branch names must follow one of these formats:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
- feature/KPC-<NUMBER>
|
|
44
|
+
- fix/KPC-<NUMBER>
|
|
45
|
+
- hotfix/KPC-<NUMBER>
|
|
46
|
+
- remove/KPC-<NUMBER>
|
|
47
|
+
- release/KPC-<NUMBER>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Where `<NUMBER>` is the ticket number.
|
|
51
|
+
|
|
52
|
+
## 📝 Commit Messages
|
|
53
|
+
|
|
54
|
+
Each commit message must follow this format:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
KPC-<NUMBER>:<ADD|FIX|DELETE>: <MESSAGE>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
NUMBER: Ticket number
|
|
62
|
+
|
|
63
|
+
ADD: A new feature
|
|
64
|
+
|
|
65
|
+
FIX: A feature was fixed
|
|
66
|
+
|
|
67
|
+
DELETE: Code cleaned or removed
|
|
68
|
+
|
|
69
|
+
MESSAGE: Short description of the change
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Example:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
KPC-123:ADD: Version X.X.X
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 🔀 Pull Requests
|
|
79
|
+
|
|
80
|
+
- After pushing, create a PR to the development branch
|
|
81
|
+
- A minimum of 2 reviewers must approve before merging
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"project_name": "
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
{
|
|
2
|
+
"project_name": "__PROJECT_NAME_REPLACE__",
|
|
3
|
+
"keen_server": "<__REPLACE__WITH__URL__>",
|
|
4
|
+
"entry": "src",
|
|
5
|
+
"dist": "dist",
|
|
6
|
+
"agents": [
|
|
7
|
+
{
|
|
8
|
+
"id": "__PROJECT_NAME_REPLACE__",
|
|
9
|
+
"name": "Agent-__PROJECT_NAME_REPLACE__",
|
|
10
|
+
"entry_flow": "Project",
|
|
11
|
+
"entry_node": "Start"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "keen__sketch__project",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "keen-builder"
|
|
8
|
-
},
|
|
9
|
-
"keywords": [],
|
|
10
|
-
"author": "",
|
|
11
|
-
"license": "ISC",
|
|
12
|
-
"description": "",
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"keen-builder": "^1.0.1"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "keen__sketch__project",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "keen-builder"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"description": "",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"keen-builder": "^1.0.1"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
{
|
|
2
|
-
"nodes": [],
|
|
3
|
-
"edges": [],
|
|
4
|
-
"viewport": { "x": 0, "y": 0, "zoom": 1 }
|
|
5
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"nodes": [],
|
|
3
|
+
"edges": [],
|
|
4
|
+
"viewport": { "x": 0, "y": 0, "zoom": 1 }
|
|
5
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export function debux(debux_id) {
|
|
2
|
-
return debux_id;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
global.debux = debux;
|
|
1
|
+
export function debux(debux_id) {
|
|
2
|
+
return debux_id;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
global.debux = debux;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Ignore artifacts:
|
|
2
|
-
dist
|
|
3
|
-
|
|
4
|
-
**/.git
|
|
5
|
-
**/.svn
|
|
6
|
-
**/.hg
|
|
1
|
+
# Ignore artifacts:
|
|
2
|
+
dist
|
|
3
|
+
|
|
4
|
+
**/.git
|
|
5
|
+
**/.svn
|
|
6
|
+
**/.hg
|
|
7
7
|
**/node_modules
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
{
|
|
2
|
-
"semi": true,
|
|
3
|
-
"singleQuote": true,
|
|
4
|
-
"trailingComma": "none",
|
|
5
|
-
"tabWidth": 4,
|
|
6
|
-
"printWidth": 200,
|
|
7
|
-
"bracketSpacing": true,
|
|
8
|
-
"arrowParens": "avoid",
|
|
9
|
-
"endOfLine": "lf"
|
|
10
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"semi": true,
|
|
3
|
+
"singleQuote": true,
|
|
4
|
+
"trailingComma": "none",
|
|
5
|
+
"tabWidth": 4,
|
|
6
|
+
"printWidth": 200,
|
|
7
|
+
"bracketSpacing": true,
|
|
8
|
+
"arrowParens": "avoid",
|
|
9
|
+
"endOfLine": "lf"
|
|
10
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "0.2.0",
|
|
3
|
-
"configurations": [
|
|
4
|
-
{
|
|
5
|
-
"name": "Attach to Keen",
|
|
6
|
-
"type": "node",
|
|
7
|
-
"request": "attach",
|
|
8
|
-
"address": "<__REPLACE__>",
|
|
9
|
-
"port": 9229,
|
|
10
|
-
"timeout": 30000,
|
|
11
|
-
"skipFiles": ["<node_internals>/**"],
|
|
12
|
-
"sourceMaps": true,
|
|
13
|
-
"localRoot": "${workspaceFolder}/src",
|
|
14
|
-
"remoteRoot": "/app/projects/__PROJECT_NAME_REPLACE__"
|
|
15
|
-
}
|
|
16
|
-
]
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Attach to Keen",
|
|
6
|
+
"type": "node",
|
|
7
|
+
"request": "attach",
|
|
8
|
+
"address": "<__REPLACE__>",
|
|
9
|
+
"port": 9229,
|
|
10
|
+
"timeout": 30000,
|
|
11
|
+
"skipFiles": ["<node_internals>/**"],
|
|
12
|
+
"sourceMaps": true,
|
|
13
|
+
"localRoot": "${workspaceFolder}/src",
|
|
14
|
+
"remoteRoot": "/app/projects/__PROJECT_NAME_REPLACE__"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
2
|
-
"editor.formatOnSave": true,
|
|
3
|
-
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
4
|
-
"editor.tabSize": 4,
|
|
5
|
-
"editor.detectIndentation": false,
|
|
6
|
-
"editor.insertSpaces": true
|
|
7
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"editor.formatOnSave": true,
|
|
3
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
4
|
+
"editor.tabSize": 4,
|
|
5
|
+
"editor.detectIndentation": false,
|
|
6
|
+
"editor.insertSpaces": true
|
|
7
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
[
|
|
2
|
-
|
|
1
|
+
[
|
|
2
|
+
|
|
3
3
|
]
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"project_name": "__PROJECT_NAME_REPLACE__",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
{
|
|
2
|
+
"project_name": "__PROJECT_NAME_REPLACE__",
|
|
3
|
+
"keen_server": "<__REPLACE__WITH__URL__>",
|
|
4
|
+
"entry": "src",
|
|
5
|
+
"dist": "dist",
|
|
6
|
+
"agents": [
|
|
7
|
+
{
|
|
8
|
+
"id": "__PROJECT_NAME_REPLACE__",
|
|
9
|
+
"name": "Agent-__PROJECT_NAME_REPLACE__",
|
|
10
|
+
"entry_flow": "Project",
|
|
11
|
+
"entry_node": "Start"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "__APP_NAME__",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "keen-builder"
|
|
8
|
-
},
|
|
9
|
-
"keywords": [],
|
|
10
|
-
"author": "",
|
|
11
|
-
"license": "ISC",
|
|
12
|
-
"description": "",
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"keen-builder": "^1.0.13",
|
|
15
|
-
"prettier": "^3.6.2"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "__APP_NAME__",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "keen-builder"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"description": "",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"keen-builder": "^1.0.13",
|
|
15
|
+
"prettier": "^3.6.2"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
You are a helpful assistant.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "keen-flow-instructions-v1",
|
|
3
|
+
"flowId": "Project",
|
|
4
|
+
"flowLabel": "Start",
|
|
5
|
+
"nodes": [
|
|
6
|
+
{
|
|
7
|
+
"id": "startNode_default_start",
|
|
8
|
+
"type": "startNode_",
|
|
9
|
+
"label": "Start"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "agentNode_default_agent",
|
|
13
|
+
"type": "agentNode_broadcaster__receiver_",
|
|
14
|
+
"agentRef": "Agent-__PROJECT_NAME_REPLACE__"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "endNode_default_end",
|
|
18
|
+
"type": "endNode_"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"edges": [
|
|
22
|
+
{
|
|
23
|
+
"source": "startNode_default_start",
|
|
24
|
+
"target": "agentNode_default_agent",
|
|
25
|
+
"sourceHandle": "NEXT_1",
|
|
26
|
+
"targetHandle": "IN"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"source": "agentNode_default_agent",
|
|
30
|
+
"target": "endNode_default_end",
|
|
31
|
+
"sourceHandle": "NEXT_1",
|
|
32
|
+
"targetHandle": "IN"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "keen-flow-positions-v1",
|
|
3
|
+
"viewport": {
|
|
4
|
+
"x": 0,
|
|
5
|
+
"y": 0,
|
|
6
|
+
"zoom": 1
|
|
7
|
+
},
|
|
8
|
+
"nodes": {
|
|
9
|
+
"startNode_default_start": {
|
|
10
|
+
"x": 450,
|
|
11
|
+
"y": 50
|
|
12
|
+
},
|
|
13
|
+
"agentNode_default_agent": {
|
|
14
|
+
"x": 450,
|
|
15
|
+
"y": 250
|
|
16
|
+
},
|
|
17
|
+
"endNode_default_end": {
|
|
18
|
+
"x": 450,
|
|
19
|
+
"y": 450
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,5 +1,87 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
{
|
|
2
|
+
"nodes": [
|
|
3
|
+
{
|
|
4
|
+
"id": "startNode_default_start",
|
|
5
|
+
"type": "startNode_",
|
|
6
|
+
"position": {
|
|
7
|
+
"x": 450,
|
|
8
|
+
"y": 50
|
|
9
|
+
},
|
|
10
|
+
"data": {
|
|
11
|
+
"label": "startNode_",
|
|
12
|
+
"nodeIDs": [],
|
|
13
|
+
"settings": {
|
|
14
|
+
"label": "Start"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "agentNode_default_agent",
|
|
20
|
+
"type": "agentNode_broadcaster__receiver_",
|
|
21
|
+
"position": {
|
|
22
|
+
"x": 450,
|
|
23
|
+
"y": 250
|
|
24
|
+
},
|
|
25
|
+
"data": {
|
|
26
|
+
"label": "agentNode_broadcaster__receiver_",
|
|
27
|
+
"nodeIDs": [],
|
|
28
|
+
"settings": {
|
|
29
|
+
"agentName": "Agent-__PROJECT_NAME_REPLACE__",
|
|
30
|
+
"prompts": [
|
|
31
|
+
{
|
|
32
|
+
"role": "system",
|
|
33
|
+
"content": "You are a helpful assistant."
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"llm": {
|
|
37
|
+
"company": "google",
|
|
38
|
+
"model": "gemini-2.0-flash",
|
|
39
|
+
"modelId": 4918,
|
|
40
|
+
"parameters": {
|
|
41
|
+
"temperature": 0.8,
|
|
42
|
+
"top_p": 0.8,
|
|
43
|
+
"maxTokens": 65536
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"filePaths": []
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "endNode_default_end",
|
|
52
|
+
"type": "endNode_",
|
|
53
|
+
"position": {
|
|
54
|
+
"x": 450,
|
|
55
|
+
"y": 450
|
|
56
|
+
},
|
|
57
|
+
"data": {
|
|
58
|
+
"label": "endNode_",
|
|
59
|
+
"nodeIDs": [],
|
|
60
|
+
"settings": {}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"edges": [
|
|
65
|
+
{
|
|
66
|
+
"id": "xy-edge__startNode_default_start[NEXT_1_||_startNode_default_start]-agentNode_default_agent[IN_||_agentNode_default_agent]",
|
|
67
|
+
"source": "startNode_default_start",
|
|
68
|
+
"target": "agentNode_default_agent",
|
|
69
|
+
"sourceHandle": "[NEXT_1_||_startNode_default_start]",
|
|
70
|
+
"targetHandle": "[IN_||_agentNode_default_agent]",
|
|
71
|
+
"type": "projectEdge"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "xy-edge__agentNode_default_agent[NEXT_1_||_agentNode_default_agent]-endNode_default_end[IN_||_endNode_default_end]",
|
|
75
|
+
"source": "agentNode_default_agent",
|
|
76
|
+
"target": "endNode_default_end",
|
|
77
|
+
"sourceHandle": "[NEXT_1_||_agentNode_default_agent]",
|
|
78
|
+
"targetHandle": "[IN_||_endNode_default_end]",
|
|
79
|
+
"type": "projectEdge"
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"viewport": {
|
|
83
|
+
"x": 0,
|
|
84
|
+
"y": 0,
|
|
85
|
+
"zoom": 1
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function exec() {}
|
|
1
|
+
export function exec() {}
|