shoud-cli 1.0.6 → 1.0.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/package.json +1 -1
- package/src/tools/index.js +121 -96
package/package.json
CHANGED
package/src/tools/index.js
CHANGED
|
@@ -1,115 +1,140 @@
|
|
|
1
|
-
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const os = require('os');
|
|
1
|
+
#!/usr/bin/env node
|
|
5
2
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
const { program } = require('commander');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const { login } = require('../src/auth/deviceFlow');
|
|
6
|
+
const { executeTask } = require('../src/runtime/agentLoop');
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
// ─── Original SHOUD Banner Art ──────────────────────────────
|
|
9
|
+
const BANNER_ART = [
|
|
10
|
+
" ███████╗██╗ ██╗ ██████╗ ██╗ ██╗██████╗ ",
|
|
11
|
+
" ██╔════╝██║ ██║██╔═══██╗██║ ██║██╔══██╗",
|
|
12
|
+
" ███████╗███████║██║ ██║██║ ██║██║ ██║",
|
|
13
|
+
" ╚════██║██╔══██║██║ ██║██║ ██║██║ ██║",
|
|
14
|
+
" ███████║██║ ██║╚██████╔╝╚██████╔╝██████╔╝",
|
|
15
|
+
" ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ "
|
|
16
|
+
];
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
// ─── Static Banner (no animation) ──────────────────────────
|
|
19
|
+
function printStaticBanner() {
|
|
20
|
+
const color = chalk.hex('#B5F96C');
|
|
21
|
+
console.log(color(BANNER_ART.join('\n')));
|
|
22
|
+
console.log(color(' ┌──────────────────────────────────────────────────────────┐'));
|
|
23
|
+
console.log(color(' │ Give your computer a job. │'));
|
|
24
|
+
console.log(color(' └──────────────────────────────────────────────────────────┘'));
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* On Windows, we use PowerShell with `Out-String` to get text.
|
|
27
|
-
*/
|
|
28
|
-
function executeShell(commandString) {
|
|
29
|
-
if (!commandString || commandString.trim().length === 0) {
|
|
30
|
-
throw new Error('Empty command.');
|
|
31
|
-
}
|
|
27
|
+
// ─── Animated Banner (for help) ─────────────────────────────
|
|
28
|
+
const SLEEP = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const escaped = commandString.replace(/"/g, '`"');
|
|
38
|
-
// Wrap in a PowerShell script block and pipe to Out-String
|
|
39
|
-
finalCommand = `& { ${escaped} } | Out-String -Width 4096`;
|
|
30
|
+
async function renderAnimatedBanner() {
|
|
31
|
+
if (!process.stdout.isTTY) {
|
|
32
|
+
printStaticBanner();
|
|
33
|
+
return;
|
|
40
34
|
}
|
|
41
35
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
const colorGradients = [
|
|
37
|
+
['#364B1D', '#5E8232', '#86B947', '#B5F96C'],
|
|
38
|
+
['#5E8232', '#86B947', '#B5F96C', '#DDFFA8'],
|
|
39
|
+
['#86B947', '#B5F96C', '#FFFFFF', '#B5F96C'],
|
|
40
|
+
['#B5F96C', '#B5F96C', '#B5F96C', '#9EEB49']
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
for (const colors of colorGradients) {
|
|
44
|
+
process.stdout.write('\x1B[?25l');
|
|
45
|
+
process.stdout.write('\r\x1B[K');
|
|
46
|
+
console.clear();
|
|
47
|
+
console.log();
|
|
48
|
+
|
|
49
|
+
BANNER_ART.forEach((line, index) => {
|
|
50
|
+
const color = colors[index % colors.length];
|
|
51
|
+
console.log(chalk.hex(color).bold(line));
|
|
50
52
|
});
|
|
51
|
-
const trimmed = output.trim();
|
|
52
|
-
return trimmed || 'Command executed successfully with no output.';
|
|
53
|
-
} catch (err) {
|
|
54
|
-
// If the command fails, return the error message
|
|
55
|
-
if (err.stderr) {
|
|
56
|
-
return `Error: ${err.stderr.trim()}`;
|
|
57
|
-
}
|
|
58
|
-
if (err.stdout) {
|
|
59
|
-
// Some commands output to stdout even on failure (e.g., `dir`)
|
|
60
|
-
return err.stdout.trim();
|
|
61
|
-
}
|
|
62
|
-
throw new Error(`Command execution failed: ${err.message}`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
53
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
} catch (err) {
|
|
80
|
-
throw new Error(`Failed to read file: ${err.message}`);
|
|
54
|
+
console.log(
|
|
55
|
+
chalk.hex('#3B472E')(
|
|
56
|
+
' ┌──────────────────────────────────────────────────────────┐\n' +
|
|
57
|
+
' │'
|
|
58
|
+
) +
|
|
59
|
+
chalk.hex('#B5F96C').bold(' Give your computer a job. ') +
|
|
60
|
+
chalk.hex('#3B472E')(
|
|
61
|
+
'│\n' +
|
|
62
|
+
' └──────────────────────────────────────────────────────────┘\n'
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
await SLEEP(75);
|
|
81
67
|
}
|
|
68
|
+
|
|
69
|
+
process.stdout.write('\x1B[?25h');
|
|
82
70
|
}
|
|
83
71
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
72
|
+
// ─── Custom Help ──────────────────────────────────────────────
|
|
73
|
+
async function customHelp() {
|
|
74
|
+
console.log(chalk.hex('#B5F96C').bold('\n SHOUD Terminal Agent - Command Reference\n'));
|
|
75
|
+
console.log(chalk.gray(' Usage: shoud [command] OR shoud "[prompt]"\n'));
|
|
76
|
+
|
|
77
|
+
console.log(chalk.white.bold(' Commands:'));
|
|
78
|
+
console.log(` ${chalk.hex('#B5F96C')('shoud login')} Authenticate this device with your Google account.`);
|
|
79
|
+
console.log(` ${chalk.hex('#B5F96C')('shoud help')} Display this help menu.`);
|
|
80
|
+
console.log(` ${chalk.hex('#B5F96C')('shoud status')} Check your current credit balance and active plan.`);
|
|
81
|
+
console.log(` ${chalk.hex('#B5F96C')('shoud --version')} Show the version number.\n`);
|
|
82
|
+
|
|
83
|
+
console.log(chalk.white.bold(' Autonomous Execution:'));
|
|
84
|
+
console.log(chalk.gray(' Wrap your instructions in quotes to trigger the agent loop.'));
|
|
85
|
+
console.log(` ${chalk.hex('#B5F96C')('>')} shoud "Refactor the auth middleware to use JWTs"`);
|
|
86
|
+
console.log(` ${chalk.hex('#B5F96C')('>')} shoud "Run npm test and fix any failing test cases"\n`);
|
|
96
87
|
}
|
|
97
88
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
89
|
+
// ─── Main ──────────────────────────────────────────────────────
|
|
90
|
+
async function main() {
|
|
91
|
+
const args = process.argv.slice(2);
|
|
92
|
+
|
|
93
|
+
// Intercept help, version, and empty input
|
|
94
|
+
if (args.length === 0 ||
|
|
95
|
+
args[0] === 'help' || args[0] === '--help' || args[0] === '-h' ||
|
|
96
|
+
args[0] === '--version' || args[0] === '-v') {
|
|
97
|
+
if (args[0] === '--version' || args[0] === '-v') {
|
|
98
|
+
program.version('1.0.6');
|
|
99
|
+
program.parse(process.argv);
|
|
100
|
+
return;
|
|
109
101
|
}
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
await renderAnimatedBanner();
|
|
103
|
+
await customHelp();
|
|
104
|
+
return;
|
|
112
105
|
}
|
|
106
|
+
|
|
107
|
+
program
|
|
108
|
+
.version('1.0.6')
|
|
109
|
+
.description('SHOUD Terminal Agent');
|
|
110
|
+
|
|
111
|
+
program
|
|
112
|
+
.command('login')
|
|
113
|
+
.description('Authenticate this device with your SHOUD account')
|
|
114
|
+
.action(login);
|
|
115
|
+
|
|
116
|
+
// Placeholder for status
|
|
117
|
+
program
|
|
118
|
+
.command('status')
|
|
119
|
+
.description('Check your current credit balance and active plan')
|
|
120
|
+
.action(() => {
|
|
121
|
+
console.log(chalk.yellow(' Status command not yet implemented.'));
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
program
|
|
125
|
+
.argument('[prompt...]', 'The task you want SHOUD to execute')
|
|
126
|
+
.action(async (promptArr) => {
|
|
127
|
+
if (!promptArr || promptArr.length === 0) {
|
|
128
|
+
console.log(chalk.gray(' Usage: shoud "fix the build errors"'));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const taskPrompt = promptArr.join(' ');
|
|
132
|
+
await executeTask(taskPrompt);
|
|
133
|
+
// ✅ After task completes, show the static banner
|
|
134
|
+
printStaticBanner();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
program.parse(process.argv);
|
|
113
138
|
}
|
|
114
139
|
|
|
115
|
-
|
|
140
|
+
main();
|