@series-inc/stowkit-cli 0.1.30 → 0.1.31
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/cli.js +8 -2
- package/dist/init.d.ts +2 -0
- package/dist/init.js +98 -0
- package/package.json +3 -3
- package/skill.md +2 -1
package/dist/cli.js
CHANGED
|
@@ -38,7 +38,9 @@ checkForUpdate();
|
|
|
38
38
|
function printUsage() {
|
|
39
39
|
console.log(`
|
|
40
40
|
Usage:
|
|
41
|
-
stowkit init [dir] Initialize a StowKit project
|
|
41
|
+
stowkit init [dir] Initialize a StowKit project (interactive menu)
|
|
42
|
+
stowkit init --with-engine Initialize with 3D engine included
|
|
43
|
+
stowkit init --no-engine Initialize without 3D engine (skip prompt)
|
|
42
44
|
stowkit init --update [dir] Update AI skill files to match installed CLI version
|
|
43
45
|
stowkit build [dir] Full build: scan + process + pack
|
|
44
46
|
stowkit scan [dir] Detect new assets, generate .stowmeta defaults
|
|
@@ -105,7 +107,11 @@ async function main() {
|
|
|
105
107
|
try {
|
|
106
108
|
switch (command) {
|
|
107
109
|
case 'init':
|
|
108
|
-
await initProject(projectDir, {
|
|
110
|
+
await initProject(projectDir, {
|
|
111
|
+
update: args.includes('--update'),
|
|
112
|
+
withEngine: args.includes('--with-engine'),
|
|
113
|
+
noEngine: args.includes('--no-engine'),
|
|
114
|
+
});
|
|
109
115
|
break;
|
|
110
116
|
case 'update': {
|
|
111
117
|
const currentVersion = getVersion();
|
package/dist/init.d.ts
CHANGED
package/dist/init.js
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
+
import * as readline from 'node:readline';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
+
async function promptMenu(question, choices) {
|
|
6
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
console.log(`\n${question}\n`);
|
|
9
|
+
for (let i = 0; i < choices.length; i++) {
|
|
10
|
+
console.log(` ${i + 1}) ${choices[i]}`);
|
|
11
|
+
}
|
|
12
|
+
console.log('');
|
|
13
|
+
const ask = () => {
|
|
14
|
+
rl.question('Choose [1]: ', (answer) => {
|
|
15
|
+
const trimmed = answer.trim();
|
|
16
|
+
if (trimmed === '') {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(0);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const num = parseInt(trimmed, 10);
|
|
22
|
+
if (num >= 1 && num <= choices.length) {
|
|
23
|
+
rl.close();
|
|
24
|
+
resolve(num - 1);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log(` Please enter 1-${choices.length}`);
|
|
28
|
+
ask();
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
ask();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
4
34
|
export async function initProject(projectDir, opts) {
|
|
5
35
|
const absDir = path.resolve(projectDir);
|
|
6
36
|
const configPath = path.join(absDir, '.felicityproject');
|
|
@@ -15,6 +45,7 @@ export async function initProject(projectDir, opts) {
|
|
|
15
45
|
process.exit(1);
|
|
16
46
|
}
|
|
17
47
|
await copySkillFiles(absDir);
|
|
48
|
+
await copyEngineSkillFiles(absDir);
|
|
18
49
|
console.log('Updated AI skill files:');
|
|
19
50
|
console.log(' .claude/skills/stowkit/SKILL.md');
|
|
20
51
|
console.log(' .cursor/rules/stowkit.mdc');
|
|
@@ -29,6 +60,16 @@ export async function initProject(projectDir, opts) {
|
|
|
29
60
|
catch {
|
|
30
61
|
// Does not exist — create it
|
|
31
62
|
}
|
|
63
|
+
// Prompt for engine setup unless explicitly set via flag
|
|
64
|
+
let withEngine = opts?.withEngine ?? false;
|
|
65
|
+
const noEngine = opts?.noEngine ?? false;
|
|
66
|
+
if (!withEngine && !noEngine && process.stdin.isTTY) {
|
|
67
|
+
const choice = await promptMenu('What would you like to set up?', [
|
|
68
|
+
'StowKit (asset pipeline only)',
|
|
69
|
+
'StowKit + 3D Engine (includes @series-inc/rundot-3d-engine)',
|
|
70
|
+
]);
|
|
71
|
+
withEngine = choice === 1;
|
|
72
|
+
}
|
|
32
73
|
// Create srcArtDir with .gitignore for cache files
|
|
33
74
|
const srcArtDir = 'assets';
|
|
34
75
|
await fs.mkdir(path.join(absDir, srcArtDir), { recursive: true });
|
|
@@ -72,10 +113,36 @@ export async function initProject(projectDir, opts) {
|
|
|
72
113
|
console.log(` Output dir: public/cdn-assets/`);
|
|
73
114
|
console.log(` Config: .felicityproject`);
|
|
74
115
|
console.log(` AI skills: .claude/skills/stowkit/SKILL.md, .cursor/rules/stowkit.mdc`);
|
|
116
|
+
// Install engine if selected
|
|
117
|
+
if (withEngine) {
|
|
118
|
+
await installEngine(absDir);
|
|
119
|
+
}
|
|
75
120
|
console.log('');
|
|
76
121
|
console.log('Drop your assets (PNG, JPG, FBX, WAV, etc.) into assets/');
|
|
77
122
|
console.log('Then run: stowkit build');
|
|
78
123
|
}
|
|
124
|
+
async function installEngine(absDir) {
|
|
125
|
+
console.log('');
|
|
126
|
+
console.log('Installing @series-inc/rundot-3d-engine and three...');
|
|
127
|
+
const { execSync } = await import('node:child_process');
|
|
128
|
+
try {
|
|
129
|
+
execSync('npm install @series-inc/rundot-3d-engine three', {
|
|
130
|
+
cwd: absDir,
|
|
131
|
+
stdio: 'inherit',
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
console.error('Failed to install engine packages. You can install manually:');
|
|
136
|
+
console.error(' npm install @series-inc/rundot-3d-engine three');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
await copyEngineSkillFiles(absDir);
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log(' 3D Engine installed:');
|
|
142
|
+
console.log(' @series-inc/rundot-3d-engine');
|
|
143
|
+
console.log(' three');
|
|
144
|
+
console.log(' AI skills: .claude/skills/stowkit-engine/SKILL.md, .cursor/rules/stowkit-engine.mdc');
|
|
145
|
+
}
|
|
79
146
|
async function copySkillFiles(absDir) {
|
|
80
147
|
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
81
148
|
const skillSrc = path.resolve(thisDir, '../skill.md');
|
|
@@ -92,3 +159,34 @@ async function copySkillFiles(absDir) {
|
|
|
92
159
|
// Skill file not found in package — skip silently
|
|
93
160
|
}
|
|
94
161
|
}
|
|
162
|
+
async function copyEngineSkillFiles(absDir) {
|
|
163
|
+
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
164
|
+
const candidates = [
|
|
165
|
+
// Monorepo dev: sibling folder
|
|
166
|
+
path.resolve(thisDir, '../../stowkit-engine/SKILL.md'),
|
|
167
|
+
// Installed in project's node_modules
|
|
168
|
+
path.join(absDir, 'node_modules/@series-inc/rundot-3d-engine/SKILL.md'),
|
|
169
|
+
// Installed as dep of CLI: nested node_modules
|
|
170
|
+
path.resolve(thisDir, '../node_modules/@series-inc/rundot-3d-engine/SKILL.md'),
|
|
171
|
+
// Hoisted in global node_modules
|
|
172
|
+
path.resolve(thisDir, '../../../@series-inc/rundot-3d-engine/SKILL.md'),
|
|
173
|
+
];
|
|
174
|
+
let skillContent = null;
|
|
175
|
+
for (const candidate of candidates) {
|
|
176
|
+
try {
|
|
177
|
+
skillContent = await fs.readFile(candidate, 'utf-8');
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// not found, try next
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (!skillContent)
|
|
185
|
+
return;
|
|
186
|
+
const claudeDir = path.join(absDir, '.claude', 'skills', 'stowkit-engine');
|
|
187
|
+
await fs.mkdir(claudeDir, { recursive: true });
|
|
188
|
+
await fs.writeFile(path.join(claudeDir, 'SKILL.md'), skillContent);
|
|
189
|
+
const cursorDir = path.join(absDir, '.cursor', 'rules');
|
|
190
|
+
await fs.mkdir(cursorDir, { recursive: true });
|
|
191
|
+
await fs.writeFile(path.join(cursorDir, 'stowkit-engine.mdc'), `---\ndescription: Rundot 3D Engine — VenusGame, GameObject, Component, physics, animations, StowKit asset loading\nalwaysApply: true\n---\n\n${skillContent}`);
|
|
192
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@series-inc/stowkit-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"stowkit": "./dist/cli.js"
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"dev": "tsc --watch"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@series-inc/stowkit-packer-gui": "^0.1.
|
|
21
|
-
"@series-inc/stowkit-editor": "^0.1.
|
|
20
|
+
"@series-inc/stowkit-packer-gui": "^0.1.17",
|
|
21
|
+
"@series-inc/stowkit-editor": "^0.1.3",
|
|
22
22
|
"draco3d": "^1.5.7",
|
|
23
23
|
"fbx-parser": "^2.1.3",
|
|
24
24
|
"@strangeape/ffmpeg-audio-wasm": "^0.1.0",
|
package/skill.md
CHANGED
|
@@ -36,7 +36,8 @@ A StowKit project has a `.felicityproject` JSON file at its root:
|
|
|
36
36
|
## CLI Commands
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
stowkit init [dir] # Scaffold a new project (
|
|
39
|
+
stowkit init [dir] # Scaffold a new project (interactive menu: pipeline only or with 3D engine)
|
|
40
|
+
stowkit init --with-engine # Scaffold with 3D engine pre-installed
|
|
40
41
|
stowkit init --update [dir] # Update AI skill files to match installed CLI version
|
|
41
42
|
stowkit update # Update CLI to latest version and refresh skill files
|
|
42
43
|
stowkit version # Show installed version
|