serpentstack 0.2.5 → 0.2.9

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.
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { error, bold, dim, green, cyan, getVersion, printHeader } from '../lib/utils/ui.js';
3
+ import { error, bold, dim, green, cyan, yellow, getVersion, printHeader, divider } from '../lib/utils/ui.js';
4
+
5
+ // Short flag aliases
6
+ const FLAG_ALIASES = { f: 'force', h: 'help', v: 'version', a: 'all' };
4
7
 
5
8
  function parseArgs(args) {
6
9
  const flags = {};
@@ -9,6 +12,13 @@ function parseArgs(args) {
9
12
  if (arg.startsWith('--')) {
10
13
  const [key, val] = arg.slice(2).split('=');
11
14
  flags[key] = val ?? true;
15
+ } else if (arg.startsWith('-') && arg.length > 1 && !arg.startsWith('--')) {
16
+ // Short flags: -f, -h, -v, -a, or combined like -fa
17
+ for (const ch of arg.slice(1)) {
18
+ const long = FLAG_ALIASES[ch];
19
+ if (long) flags[long] = true;
20
+ else flags[ch] = true;
21
+ }
12
22
  } else {
13
23
  positional.push(arg);
14
24
  }
@@ -16,35 +26,67 @@ function parseArgs(args) {
16
26
  return { flags, positional };
17
27
  }
18
28
 
29
+ // Known commands for fuzzy matching on typos
30
+ const KNOWN_COMMANDS = ['stack', 'skills', 'persistent'];
31
+
32
+ function suggestCommand(input) {
33
+ const lower = input.toLowerCase();
34
+ let best = null, bestDist = 3; // threshold: edit distance ≤ 2
35
+ for (const cmd of KNOWN_COMMANDS) {
36
+ if (cmd.startsWith(lower) || lower.startsWith(cmd)) return cmd;
37
+ const d = editDistance(lower, cmd);
38
+ if (d < bestDist) { bestDist = d; best = cmd; }
39
+ }
40
+ return best;
41
+ }
42
+
43
+ function editDistance(a, b) {
44
+ const m = a.length, n = b.length;
45
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1));
46
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
47
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
48
+ for (let i = 1; i <= m; i++)
49
+ for (let j = 1; j <= n; j++)
50
+ dp[i][j] = Math.min(
51
+ dp[i - 1][j] + 1,
52
+ dp[i][j - 1] + 1,
53
+ dp[i - 1][j - 1] + (a[i - 1] !== b[j - 1] ? 1 : 0),
54
+ );
55
+ return dp[m][n];
56
+ }
57
+
19
58
  function showHelp() {
20
59
  printHeader();
21
- console.log(` ${bold('Usage:')} serpentstack <command> [options]
22
-
23
- ${bold(green('New projects'))}
24
- ${cyan('stack new')} <name> Scaffold a full project from the template
25
- ${cyan('stack update')} Update template-level files to latest
26
-
27
- ${bold(green('Any project'))}
28
- ${cyan('skills')} Download base skills + persistent agent configs
29
- ${cyan('skills update')} Update base skills to latest versions
30
- ${cyan('persistent')} Manage and launch persistent agents
31
- ${cyan('persistent')} --stop Stop all running agents
32
- ${cyan('persistent')} --reconfigure Re-run setup (change models, enable/disable)
33
-
34
- ${bold('Options:')}
35
- --force Overwrite existing files
36
- --all Include new files in updates (skills update)
37
- --version Show version
38
- --help Show this help
39
-
40
- ${dim('Examples:')}
41
- ${dim('$')} serpentstack stack new my-saas-app
42
- ${dim('$')} serpentstack skills
43
- ${dim('$')} serpentstack persistent
44
- ${dim('$')} serpentstack persistent --stop
45
-
46
- ${dim('Docs: https://github.com/Benja-Pauls/SerpentStack')}
47
- `);
60
+ console.log(` ${dim('Deployable fullstack templates + AI agent skills for any project')}`);
61
+ console.log();
62
+
63
+ divider('New projects');
64
+ console.log(` ${cyan('stack new')} ${dim('<name>')} Scaffold a full project from the template`);
65
+ console.log(` ${cyan('stack update')} Update template-level files to latest`);
66
+ console.log();
67
+
68
+ divider('Any project');
69
+ console.log(` ${cyan('skills')} Download all skills + persistent agent configs`);
70
+ console.log(` ${cyan('skills update')} Update base skills to latest versions`);
71
+ console.log(` ${cyan('persistent')} Manage and launch persistent background agents`);
72
+ console.log(` ${cyan('persistent')} ${dim('--stop')} Stop all running agents`);
73
+ console.log(` ${cyan('persistent')} ${dim('--reconfigure')} Change models, enable/disable agents`);
74
+ console.log();
75
+
76
+ divider('Options');
77
+ console.log(` ${bold('-f')}, ${bold('--force')} Overwrite existing files`);
78
+ console.log(` ${bold('-a')}, ${bold('--all')} Include new files in updates`);
79
+ console.log(` ${bold('-v')}, ${bold('--version')} Show version`);
80
+ console.log(` ${bold('-h')}, ${bold('--help')} Show this help`);
81
+ console.log();
82
+
83
+ console.log(` ${dim('Examples:')}`);
84
+ console.log(` ${dim('$')} serpentstack stack new my-saas-app`);
85
+ console.log(` ${dim('$')} serpentstack skills`);
86
+ console.log(` ${dim('$')} serpentstack persistent`);
87
+ console.log();
88
+ console.log(` ${dim('Docs:')} ${cyan('https://github.com/Benja-Pauls/SerpentStack')}`);
89
+ console.log();
48
90
  }
49
91
 
50
92
  async function main() {
@@ -95,7 +137,12 @@ async function main() {
95
137
  await persistent({ stop: !!flags.stop, reconfigure: !!flags.reconfigure });
96
138
  } else {
97
139
  error(`Unknown command: ${bold(noun)}`);
98
- console.log(`\n Run ${bold('serpentstack --help')} to see available commands.\n`);
140
+ const suggestion = suggestCommand(noun);
141
+ if (suggestion) {
142
+ console.log(`\n Did you mean ${bold(suggestion)}? Run ${bold(`serpentstack ${suggestion}`)} or ${bold('serpentstack --help')}.\n`);
143
+ } else {
144
+ console.log(`\n Run ${bold('serpentstack --help')} to see available commands.\n`);
145
+ }
99
146
  process.exit(1);
100
147
  }
101
148
  }