ac-framework 1.0.0 → 1.0.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/package.json +1 -1
- package/src/cli.js +7 -1
- package/src/commands/init.js +34 -46
- package/src/ui/animations.js +1 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
5
|
+
import { dirname, resolve } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
4
7
|
import { initCommand } from './commands/init.js';
|
|
5
8
|
import { showBanner } from './ui/banner.js';
|
|
6
9
|
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const pkg = JSON.parse(await readFile(resolve(__dirname, '../package.json'), 'utf-8'));
|
|
12
|
+
|
|
7
13
|
const program = new Command();
|
|
8
14
|
|
|
9
15
|
program
|
|
10
16
|
.name('acfm')
|
|
11
17
|
.description('AC Framework - Agentic Coding Framework CLI')
|
|
12
|
-
.version(
|
|
18
|
+
.version(pkg.version);
|
|
13
19
|
|
|
14
20
|
program
|
|
15
21
|
.command('init')
|
package/src/commands/init.js
CHANGED
|
@@ -14,55 +14,31 @@ const __dirname = dirname(__filename);
|
|
|
14
14
|
const acGradient = gradient(['#6C5CE7', '#00CEC9', '#0984E3']);
|
|
15
15
|
const successGradient = gradient(['#00CEC9', '#00B894', '#55EFC4']);
|
|
16
16
|
|
|
17
|
+
const ALWAYS_INSTALL = ['openspec'];
|
|
18
|
+
|
|
17
19
|
async function getFrameworkFolders() {
|
|
18
20
|
const frameworkPath = resolve(__dirname, '../../framework');
|
|
19
21
|
const entries = await readdir(frameworkPath, { withFileTypes: true });
|
|
20
22
|
|
|
21
23
|
return entries
|
|
22
|
-
.filter((entry) => entry.isDirectory())
|
|
24
|
+
.filter((entry) => entry.isDirectory() && !ALWAYS_INSTALL.includes(entry.name))
|
|
23
25
|
.map((entry) => entry.name)
|
|
24
|
-
.sort((a, b) =>
|
|
25
|
-
// Hidden folders first, then normal
|
|
26
|
-
const aHidden = a.startsWith('.');
|
|
27
|
-
const bHidden = b.startsWith('.');
|
|
28
|
-
if (aHidden && !bHidden) return -1;
|
|
29
|
-
if (!aHidden && bHidden) return 1;
|
|
30
|
-
return a.localeCompare(b);
|
|
31
|
-
});
|
|
26
|
+
.sort((a, b) => a.localeCompare(b));
|
|
32
27
|
}
|
|
33
28
|
|
|
34
29
|
function buildChoices(folders) {
|
|
35
30
|
const choices = [];
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
name: label,
|
|
48
|
-
value: folder,
|
|
49
|
-
short: displayName,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (visible.length > 0) {
|
|
55
|
-
choices.push(new inquirer.Separator(chalk.hex('#636E72')(' ── Configuration ─────────────────────────')));
|
|
56
|
-
for (const folder of visible) {
|
|
57
|
-
const desc = DESCRIPTIONS[folder] || '';
|
|
58
|
-
const displayName = formatFolderName(folder);
|
|
59
|
-
const label = `${chalk.hex('#DFE6E9').bold(displayName)}${desc ? chalk.hex('#636E72')(` — ${desc}`) : ''}`;
|
|
60
|
-
choices.push({
|
|
61
|
-
name: label,
|
|
62
|
-
value: folder,
|
|
63
|
-
short: displayName,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
32
|
+
choices.push(new inquirer.Separator(chalk.hex('#636E72')(' ── AI Assistants ──────────────────────────')));
|
|
33
|
+
for (const folder of folders) {
|
|
34
|
+
const desc = DESCRIPTIONS[folder] || '';
|
|
35
|
+
const displayName = formatFolderName(folder);
|
|
36
|
+
const label = `${chalk.hex('#DFE6E9').bold(displayName)}${desc ? chalk.hex('#636E72')(` — ${desc}`) : ''}`;
|
|
37
|
+
choices.push({
|
|
38
|
+
name: label,
|
|
39
|
+
value: folder,
|
|
40
|
+
short: displayName,
|
|
41
|
+
});
|
|
66
42
|
}
|
|
67
43
|
|
|
68
44
|
return choices;
|
|
@@ -103,7 +79,10 @@ export async function initCommand() {
|
|
|
103
79
|
}
|
|
104
80
|
|
|
105
81
|
console.log(
|
|
106
|
-
chalk.hex('#B2BEC3')(` Found ${chalk.hex('#00CEC9').bold(folders.length)} modules available
|
|
82
|
+
chalk.hex('#B2BEC3')(` Found ${chalk.hex('#00CEC9').bold(folders.length)} assistant modules available`)
|
|
83
|
+
);
|
|
84
|
+
console.log(
|
|
85
|
+
chalk.hex('#636E72')(` + ${chalk.hex('#6C5CE7').bold('openspec')} will be included automatically\n`)
|
|
107
86
|
);
|
|
108
87
|
|
|
109
88
|
console.log(
|
|
@@ -137,9 +116,10 @@ export async function initCommand() {
|
|
|
137
116
|
|
|
138
117
|
console.log();
|
|
139
118
|
|
|
140
|
-
// Check for existing folders
|
|
119
|
+
// Check for existing folders (includes openspec)
|
|
120
|
+
const allForCheck = [...selected, ...ALWAYS_INSTALL];
|
|
141
121
|
const existing = [];
|
|
142
|
-
for (const folder of
|
|
122
|
+
for (const folder of allForCheck) {
|
|
143
123
|
if (await checkExisting(targetDir, folder)) {
|
|
144
124
|
existing.push(folder);
|
|
145
125
|
}
|
|
@@ -165,19 +145,20 @@ export async function initCommand() {
|
|
|
165
145
|
|
|
166
146
|
if (!overwrite) {
|
|
167
147
|
const filtered = selected.filter((f) => !existing.includes(f));
|
|
168
|
-
|
|
148
|
+
const autoFiltered = ALWAYS_INSTALL.filter((f) => !existing.includes(f));
|
|
149
|
+
if (filtered.length === 0 && autoFiltered.length === 0) {
|
|
169
150
|
console.log(chalk.hex('#636E72')('\n No new modules to install. Exiting.\n'));
|
|
170
151
|
process.exit(0);
|
|
171
152
|
}
|
|
172
153
|
selected.length = 0;
|
|
173
154
|
selected.push(...filtered);
|
|
174
155
|
console.log(
|
|
175
|
-
chalk.hex('#B2BEC3')(`\n Proceeding with ${chalk.hex('#00CEC9').bold(
|
|
156
|
+
chalk.hex('#B2BEC3')(`\n Proceeding with ${chalk.hex('#00CEC9').bold(filtered.length + autoFiltered.length)} new module(s)...\n`)
|
|
176
157
|
);
|
|
177
158
|
}
|
|
178
159
|
}
|
|
179
160
|
|
|
180
|
-
// Confirm selection
|
|
161
|
+
// Confirm selection — show selected + openspec
|
|
181
162
|
console.log(chalk.hex('#B2BEC3')(' Modules to install:\n'));
|
|
182
163
|
for (const folder of selected) {
|
|
183
164
|
const desc = DESCRIPTIONS[folder] || '';
|
|
@@ -187,6 +168,12 @@ export async function initCommand() {
|
|
|
187
168
|
(desc ? chalk.hex('#636E72')(` — ${desc}`) : '')
|
|
188
169
|
);
|
|
189
170
|
}
|
|
171
|
+
console.log(
|
|
172
|
+
chalk.hex('#6C5CE7')(' ◆ ') +
|
|
173
|
+
chalk.hex('#DFE6E9').bold('Openspec') +
|
|
174
|
+
chalk.hex('#636E72')(` — ${DESCRIPTIONS['openspec']}`) +
|
|
175
|
+
chalk.hex('#636E72').italic(' (auto)')
|
|
176
|
+
);
|
|
190
177
|
console.log();
|
|
191
178
|
|
|
192
179
|
const { confirm } = await inquirer.prompt([
|
|
@@ -205,12 +192,13 @@ export async function initCommand() {
|
|
|
205
192
|
|
|
206
193
|
console.log();
|
|
207
194
|
|
|
208
|
-
// Install modules with progress
|
|
195
|
+
// Install modules with progress — always include openspec
|
|
209
196
|
const frameworkPath = resolve(__dirname, '../../framework');
|
|
197
|
+
const allToInstall = [...selected, ...ALWAYS_INSTALL];
|
|
210
198
|
let installed = 0;
|
|
211
199
|
const errors = [];
|
|
212
200
|
|
|
213
|
-
for (const folder of
|
|
201
|
+
for (const folder of allToInstall) {
|
|
214
202
|
const spinner = createSpinner(
|
|
215
203
|
chalk.hex('#B2BEC3')(`Installing ${chalk.hex('#DFE6E9').bold(formatFolderName(folder))}...`)
|
|
216
204
|
).start();
|
package/src/ui/animations.js
CHANGED
|
@@ -23,7 +23,7 @@ export async function matrixRain(durationMs = 1500) {
|
|
|
23
23
|
|
|
24
24
|
for (let c = 0; c < cols; c++) {
|
|
25
25
|
const drop = drops[c];
|
|
26
|
-
if (drop.y < rows) {
|
|
26
|
+
if (drop.y >= 0 && drop.y < rows) {
|
|
27
27
|
const ch = chars[Math.floor(Math.random() * chars.length)];
|
|
28
28
|
grid[drop.y][c] = chalk.hex(colors[Math.floor(Math.random() * colors.length)])(ch);
|
|
29
29
|
if (drop.y > 0) {
|