@flowdevcli/flowdev 1.0.4 → 1.0.5
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/.env.example +1 -0
- package/Dockerfile +3 -3
- package/README.md +157 -0
- package/package.json +4 -3
- package/src/commands/ai/ask.js +35 -149
- package/src/commands/ai/audit.js +29 -19
- package/src/commands/ai/explain.js +31 -14
- package/src/commands/ai/readme.js +70 -0
- package/src/commands/ai/test.js +41 -19
- package/src/commands/config.js +64 -0
- package/src/commands/devops/dockerize.js +19 -0
- package/src/commands/devops/env.js +19 -0
- package/src/commands/devops/kube.js +19 -0
- package/src/commands/scaffold/find.js +19 -0
- package/src/commands/scaffold/generate.js +105 -76
- package/src/commands/system/update.js +19 -0
- package/src/commands/utils/stats.js +19 -0
- package/src/commands/utils/tree.js +19 -0
- package/src/core/cli.js +33 -0
- package/src/services/analyzer.js +19 -0
- package/src/services/file-system.js +19 -0
- package/src/templates/docker/templates.js +18 -0
- package/src/utils/engine-check.js +125 -17
- package/src/utils/logger.js +19 -0
- package/src/commands/devops/ci.js +0 -0
- package/src/commands/scaffold/readme.js +0 -54
package/.env.example
CHANGED
package/Dockerfile
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Stage 1: Build
|
|
2
|
-
FROM node:
|
|
2
|
+
FROM node:28-alpine AS builder
|
|
3
3
|
WORKDIR /app
|
|
4
4
|
COPY package*.json ./
|
|
5
5
|
RUN npm ci
|
|
6
6
|
COPY . .
|
|
7
7
|
|
|
8
8
|
# Stage 2: Production
|
|
9
|
-
FROM node:
|
|
9
|
+
FROM node:28-alpine
|
|
10
10
|
WORKDIR /app
|
|
11
11
|
COPY --from=builder /app ./
|
|
12
12
|
EXPOSE 3000
|
|
13
13
|
# Formats the command string into a JSON array for CMD
|
|
14
|
-
CMD ["npm", "
|
|
14
|
+
CMD ["npm", "start"]
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
FLOWDEV
|
|
2
|
+
=======
|
|
3
|
+
The intelligent CLI for modern workflow automation.
|
|
4
|
+
|
|
5
|
+
FlowDev is a privacy-first, offline-capable CLI tool designed to accelerate developer workflows. From scaffolding Docker environments to generating project structures using local or cloud AI, FlowDev keeps you in the flow without leaving your terminal.
|
|
6
|
+
|
|
7
|
+
> "The developer tool for the next generation."
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/flowdev)
|
|
10
|
+
[](https://packagephobia.com/result?p=flowdev)
|
|
11
|
+
[](https://www.npmjs.com/package/flowdev)
|
|
12
|
+
|
|
13
|
+
Install
|
|
14
|
+
=======
|
|
15
|
+
|
|
16
|
+
Global Installation (Recommended)
|
|
17
|
+
---------------------------------
|
|
18
|
+
To use FlowDev commands anywhere on your system:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g flowdev
|
|
22
|
+
|
|
23
|
+
Local Installation
|
|
24
|
+
|
|
25
|
+
If you prefer to use it per project:
|
|
26
|
+
Bash
|
|
27
|
+
|
|
28
|
+
npm install flowdev --save-dev
|
|
29
|
+
|
|
30
|
+
Usage
|
|
31
|
+
|
|
32
|
+
Once installed, FlowDev exposes the flowdev binary.
|
|
33
|
+
|
|
34
|
+
Check your installation:
|
|
35
|
+
|
|
36
|
+
Bash
|
|
37
|
+
flowdev --version
|
|
38
|
+
|
|
39
|
+
*Configure your environment (API keys & Models):
|
|
40
|
+
Bash
|
|
41
|
+
flowdev config
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
*Analyze your current project:
|
|
45
|
+
Bash
|
|
46
|
+
flowdev stats
|
|
47
|
+
|
|
48
|
+
*Generate a Docker environment:
|
|
49
|
+
Bash
|
|
50
|
+
flowdev dockerize
|
|
51
|
+
|
|
52
|
+
Features
|
|
53
|
+
AI & Automation (Hybrid Engine)
|
|
54
|
+
|
|
55
|
+
FlowDev integrates with Ollama for offline capabilities and supports DeepSeek for high-performance cloud reasoning.
|
|
56
|
+
|
|
57
|
+
1. Smart Assistant
|
|
58
|
+
Ask questions about code or architecture using local or cloud models.
|
|
59
|
+
Bash
|
|
60
|
+
|
|
61
|
+
flowdev ask "How do I optimize a React useEffect hook?"
|
|
62
|
+
|
|
63
|
+
2. Intelligent Audit
|
|
64
|
+
Audit your code for bugs, security, and performance using AI.
|
|
65
|
+
Bash
|
|
66
|
+
|
|
67
|
+
flowdev audit
|
|
68
|
+
|
|
69
|
+
3. Automatic Documentation
|
|
70
|
+
Generate a professional README.md for your project instantly.
|
|
71
|
+
Bash
|
|
72
|
+
|
|
73
|
+
flowdev readme
|
|
74
|
+
|
|
75
|
+
DevOps & Infrastructure
|
|
76
|
+
|
|
77
|
+
1. Dockerize
|
|
78
|
+
Instantly generate production-ready Dockerfile and docker-compose.yml files.
|
|
79
|
+
Bash
|
|
80
|
+
|
|
81
|
+
flowdev dockerize
|
|
82
|
+
|
|
83
|
+
2. Kubernetes (Kube)
|
|
84
|
+
Generate Kubernetes deployment and service manifests for your application.
|
|
85
|
+
Bash
|
|
86
|
+
|
|
87
|
+
flowdev kube
|
|
88
|
+
|
|
89
|
+
Utilities
|
|
90
|
+
|
|
91
|
+
1. Generate
|
|
92
|
+
Generate a complete project (React, Django, Vue, Angular, Express) with Git and dependencies automatically configured.
|
|
93
|
+
Bash
|
|
94
|
+
|
|
95
|
+
flowdev generate
|
|
96
|
+
|
|
97
|
+
2. Find (Pattern Search)
|
|
98
|
+
A recursive search tool optimized for developers. Ignores node_modules and binaries.
|
|
99
|
+
Bash
|
|
100
|
+
|
|
101
|
+
flowdev find "TODO" --ext js,ts
|
|
102
|
+
|
|
103
|
+
3. Stats
|
|
104
|
+
Get an instant breakdown of your project's size, file count, and language distribution.
|
|
105
|
+
Bash
|
|
106
|
+
|
|
107
|
+
flowdev stats
|
|
108
|
+
|
|
109
|
+
Requirements
|
|
110
|
+
Node.js
|
|
111
|
+
|
|
112
|
+
FlowDev requires Node.js v18+.
|
|
113
|
+
Local AI (Optional)
|
|
114
|
+
|
|
115
|
+
To use local AI features, you must have Ollama running locally.
|
|
116
|
+
|
|
117
|
+
Install Ollama: ollama.com
|
|
118
|
+
|
|
119
|
+
Start the service: ollama serve
|
|
120
|
+
|
|
121
|
+
FlowDev handles the rest.
|
|
122
|
+
|
|
123
|
+
Cloud AI (Optional)
|
|
124
|
+
|
|
125
|
+
To use Cloud features (DeepSeek), configure your API key via flowdev config.
|
|
126
|
+
Documentation
|
|
127
|
+
flowdev generate
|
|
128
|
+
|
|
129
|
+
Provisions full-stack templates. Includes a fail-safe execution wrapper that generates a flowdev-debug.log if an installation fails.
|
|
130
|
+
flowdev audit
|
|
131
|
+
|
|
132
|
+
Uses AI to scan for security vulnerabilities and logic flaws. Perfect for pre-commit checks.
|
|
133
|
+
flowdev dockerize
|
|
134
|
+
|
|
135
|
+
Generates optimized configurations using multi-stage builds and non-root security practices.
|
|
136
|
+
flowdev env
|
|
137
|
+
|
|
138
|
+
Scans your project code and generates a .env.example file based on your environment variable usage.
|
|
139
|
+
FAQ
|
|
140
|
+
Does FlowDev send my code to the cloud?
|
|
141
|
+
|
|
142
|
+
By default, No. Local AI processing happens on your machine via Ollama. Cloud processing is only used if you explicitly configure it and choose a cloud model.
|
|
143
|
+
Do I need an API Key?
|
|
144
|
+
|
|
145
|
+
No for local use. Yes if you wish to use cloud models like DeepSeek.
|
|
146
|
+
Why "flowdev"?
|
|
147
|
+
|
|
148
|
+
Because switching contexts breaks your flow. FlowDev keeps you in the terminal, automating the boring stuff so you can focus on the code.
|
|
149
|
+
Changelog
|
|
150
|
+
|
|
151
|
+
See CHANGELOG.md for details on recent updates.
|
|
152
|
+
License
|
|
153
|
+
|
|
154
|
+
[MIT](https://www.google.com/search?q=LICENSE)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowdevcli/flowdev",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "AI-powered CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,12 +26,13 @@
|
|
|
26
26
|
"boxen": "^7.1.1",
|
|
27
27
|
"chalk": "^5.3.0",
|
|
28
28
|
"commander": "^11.1.0",
|
|
29
|
+
"conf": "^15.1.0",
|
|
29
30
|
"dotenv": "^16.3.1",
|
|
30
31
|
"execa": "^8.0.1",
|
|
31
32
|
"figlet": "^1.7.0",
|
|
32
33
|
"fs-extra": "^11.1.1",
|
|
33
34
|
"gradient-string": "^2.0.2",
|
|
34
|
-
"inquirer": "^9.
|
|
35
|
+
"inquirer": "^9.3.8",
|
|
35
36
|
"is-binary-path": "^3.0.0",
|
|
36
37
|
"mammoth": "^1.11.0",
|
|
37
38
|
"ollama": "^0.6.3",
|
|
@@ -46,4 +47,4 @@
|
|
|
46
47
|
"publishConfig": {
|
|
47
48
|
"access": "public"
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
|
+
}
|
package/src/commands/ai/ask.js
CHANGED
|
@@ -1,94 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FlowDev - Intelligent CLI tool
|
|
3
|
+
* @module flowdev
|
|
4
|
+
* @version 1.0.5
|
|
5
|
+
* * @license MIT
|
|
6
|
+
* Copyright (c) 2026 FlowDev Technologies.
|
|
7
|
+
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
* * The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
*/
|
|
19
|
+
|
|
2
20
|
import chalk from 'chalk';
|
|
3
21
|
import ora from 'ora';
|
|
4
22
|
import fs from 'fs-extra';
|
|
5
|
-
import { exec, spawn } from 'node:child_process';
|
|
6
|
-
import { promisify } from 'util';
|
|
7
23
|
import { logger } from '../../utils/logger.js';
|
|
8
|
-
|
|
9
|
-
const execAsync = promisify(exec);
|
|
10
|
-
|
|
11
|
-
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
async function waitForOllamaServer({ retries = 15, delayMs = 1000 } = {}) {
|
|
15
|
-
for (let i = 0; i < retries; i++) {
|
|
16
|
-
try {
|
|
17
|
-
await ollama.list();
|
|
18
|
-
return true;
|
|
19
|
-
} catch (e) {
|
|
20
|
-
|
|
21
|
-
logger.debug(`Ollama not ready (attempt ${i + 1}/${retries}): ${e.message}`);
|
|
22
|
-
await sleep(delayMs);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function installOllamaEngine(spinner) {
|
|
29
|
-
const isWindows = process.platform === 'win32';
|
|
30
|
-
const installCmd = isWindows
|
|
31
|
-
? 'winget install Ollama.Ollama --silent --accept-source-agreements'
|
|
32
|
-
: 'curl -fsSL https://ollama.com/install.sh | sh';
|
|
33
|
-
|
|
34
|
-
spinner.text = chalk.yellow('Downloading FlowDev engine package... (This may take a while)');
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
|
|
38
|
-
const { stdout, stderr } = await execAsync(installCmd, { maxBuffer: 10 * 1024 * 1024 });
|
|
39
|
-
logger.debug('install stdout: ' + (stdout || '').toString().slice(0, 2000));
|
|
40
|
-
logger.debug('install stderr: ' + (stderr || '').toString().slice(0, 2000));
|
|
41
|
-
|
|
42
|
-
spinner.succeed(chalk.green('FlowDev Engine installed successfully!'));
|
|
43
|
-
|
|
44
|
-
await sleep(1500);
|
|
45
|
-
} catch (error) {
|
|
46
|
-
|
|
47
|
-
spinner.fail(chalk.red('Automatic installation failed (admin rights or network?)'));
|
|
48
|
-
logger.error('Automatic installation error: ' + (error.message || error));
|
|
49
|
-
if (error.stdout || error.stderr) {
|
|
50
|
-
logger.error('Installer output (truncated):');
|
|
51
|
-
logger.error((error.stdout || '').toString().slice(0, 500));
|
|
52
|
-
logger.error((error.stderr || '').toString().slice(0, 500));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
logger.error(`Try installing it manually: ${isWindows ? 'winget install Ollama.Ollama' : 'curl -fsSL https://ollama.com/install.sh | sh'}`);
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function ensureOllamaRunning(spinner) {
|
|
61
|
-
try {
|
|
62
|
-
|
|
63
|
-
await execAsync('ollama --version');
|
|
64
|
-
} catch (e) {
|
|
65
|
-
logger.info('Ollama binary not found. Attempting automatic install...');
|
|
66
|
-
|
|
67
|
-
await installOllamaEngine(spinner);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (await waitForOllamaServer({ retries: 3, delayMs: 1000 })) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
logger.info('Starting ollama serve in background...');
|
|
77
|
-
try {
|
|
78
|
-
|
|
79
|
-
const child = spawn('ollama', ['serve'], { detached: true, stdio: 'ignore' });
|
|
80
|
-
child.unref();
|
|
81
|
-
} catch (spawnErr) {
|
|
82
|
-
logger.error('Failed to spawn ollama serve: ' + spawnErr.message);
|
|
83
|
-
throw spawnErr;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const ready = await waitForOllamaServer({ retries: 30, delayMs: 1000 });
|
|
88
|
-
if (!ready) {
|
|
89
|
-
throw new Error('Ollama server did not start in time. Check logs or run `ollama serve` manually.');
|
|
90
|
-
}
|
|
91
|
-
}
|
|
24
|
+
import { getAIResponse } from '../../utils/engine-check.js';
|
|
92
25
|
|
|
93
26
|
export async function askCommand(question) {
|
|
94
27
|
if (!question) {
|
|
@@ -99,80 +32,33 @@ export async function askCommand(question) {
|
|
|
99
32
|
let spinner = ora(chalk.cyan('Initialization...')).start();
|
|
100
33
|
|
|
101
34
|
try {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const modelName = process.env.OLLAMA_MODEL || 'llama3';
|
|
106
|
-
|
|
107
|
-
let hasModel = false;
|
|
108
|
-
try {
|
|
109
|
-
const models = await ollama.list();
|
|
110
|
-
hasModel = Array.isArray(models?.models) && models.models.some((m) => m.name?.startsWith(modelName));
|
|
111
|
-
} catch (err) {
|
|
112
|
-
logger.debug('Error listing models: ' + (err?.message || err));
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (!hasModel) {
|
|
117
|
-
spinner.text = chalk.magenta('First launch: Configuring neurons...');
|
|
118
|
-
spinner.start();
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
await ollama.pull({ model: modelName });
|
|
122
|
-
spinner.succeed(chalk.green('AI brain in charge !'));
|
|
123
|
-
} catch (pullErr) {
|
|
124
|
-
spinner.fail(chalk.red('Failed to download model.'));
|
|
125
|
-
logger.error('ollama.pull error: ' + (pullErr?.message || pullErr));
|
|
126
|
-
throw pullErr;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
spinner = ora(chalk.cyan('Thinking...')).start();
|
|
131
|
-
} else {
|
|
132
|
-
spinner.text = chalk.cyan('Thinking...');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
let context = 'flowdev intelligent CLI tool';
|
|
35
|
+
let context = 'You are FlowDev, an intelligent CLI assistant.';
|
|
137
36
|
try {
|
|
138
37
|
if (await fs.pathExists('package.json')) {
|
|
139
38
|
const pkg = await fs.readJson('package.json');
|
|
140
|
-
if (pkg?.name) context += ` CURRENT CONTEXT:
|
|
39
|
+
if (pkg?.name) context += ` CURRENT CONTEXT: User is in project "${pkg.name}".`;
|
|
141
40
|
}
|
|
142
|
-
} catch (e) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
{ role: 'user', content: question },
|
|
151
|
-
],
|
|
152
|
-
stream: true,
|
|
153
|
-
});
|
|
41
|
+
} catch (e) {}
|
|
42
|
+
const responseStream = await getAIResponse(
|
|
43
|
+
[
|
|
44
|
+
{ role: 'system', content: context },
|
|
45
|
+
{ role: 'user', content: question }
|
|
46
|
+
],
|
|
47
|
+
spinner
|
|
48
|
+
);
|
|
154
49
|
|
|
155
|
-
|
|
156
50
|
spinner.stop();
|
|
51
|
+
console.log(chalk.bold.magenta('FlowDev:'));
|
|
157
52
|
|
|
158
|
-
for await (const part of
|
|
53
|
+
for await (const part of responseStream) {
|
|
159
54
|
const content = part?.message?.content;
|
|
160
55
|
if (typeof content === 'string') {
|
|
161
56
|
process.stdout.write(chalk.white(content));
|
|
162
57
|
}
|
|
163
58
|
}
|
|
164
|
-
|
|
165
59
|
process.stdout.write('\n');
|
|
166
60
|
} catch (error) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
logger.error('askCommand error: ' + (error?.message || error));
|
|
171
|
-
|
|
172
|
-
if (error?.code === 'ENOENT') {
|
|
173
|
-
console.log(chalk.red('\nUnable to find or install Ollama automatically.'));
|
|
174
|
-
} else {
|
|
175
|
-
console.log(chalk.red(`\nError: ${error?.message || error}`));
|
|
176
|
-
}
|
|
61
|
+
spinner.stop();
|
|
62
|
+
logger.error('Error: ' + error.message);
|
|
177
63
|
}
|
|
178
|
-
}
|
|
64
|
+
}
|
package/src/commands/ai/audit.js
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FlowDev - Intelligent CLI tool
|
|
3
|
+
* @module flowdev
|
|
4
|
+
* @version 1.0.5
|
|
5
|
+
* * @license MIT
|
|
6
|
+
* Copyright (c) 2026 FlowDev Technologies.
|
|
7
|
+
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
* * The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
*/
|
|
19
|
+
|
|
2
20
|
import chalk from 'chalk';
|
|
3
21
|
import ora from 'ora';
|
|
4
22
|
import fs from 'fs-extra';
|
|
5
23
|
import path from 'path';
|
|
6
|
-
import {
|
|
24
|
+
import { getAIResponse } from '../../utils/engine-check.js';
|
|
7
25
|
import { logger } from '../../utils/logger.js';
|
|
8
26
|
|
|
9
27
|
const AUDIT_EXTENSIONS = ['.js', '.ts', '.py', '.php', '.go', '.jsx', '.tsx', '.vue'];
|
|
@@ -31,18 +49,15 @@ export async function auditCommand() {
|
|
|
31
49
|
return;
|
|
32
50
|
}
|
|
33
51
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
spinner.text = chalk.magenta(`Auditing ${files.length} files...`);
|
|
52
|
+
spinner.text = chalk.magenta(`Preparing audit for ${files.length} files...`);
|
|
37
53
|
|
|
38
54
|
let codeContext = "";
|
|
39
|
-
for (const file of files.slice(0,
|
|
55
|
+
for (const file of files.slice(0, 15)) {
|
|
40
56
|
const content = await fs.readFile(file, 'utf-8');
|
|
41
57
|
codeContext += `\n--- File: ${path.basename(file)} ---\n${content}\n`;
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
const prompt = `
|
|
45
|
-
As an Expert Security Auditor,
|
|
46
61
|
Analyze the following code for:
|
|
47
62
|
1. Potential Bugs or logic errors.
|
|
48
63
|
2. Security vulnerabilities (exposed keys, unsafe inputs).
|
|
@@ -50,26 +65,21 @@ export async function auditCommand() {
|
|
|
50
65
|
4. Code quality and Best Practices.
|
|
51
66
|
|
|
52
67
|
Provide a concise report with clear headings and bullet points.
|
|
53
|
-
If the code is perfect, congratulate the developer.
|
|
54
68
|
|
|
55
69
|
Code to analyze:
|
|
56
|
-
${codeContext}
|
|
70
|
+
${codeContext.substring(0, 30000)}
|
|
57
71
|
`;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
stream: true,
|
|
63
|
-
});
|
|
72
|
+
const responseStream = await getAIResponse(
|
|
73
|
+
[{ role: 'user', content: prompt }],
|
|
74
|
+
spinner
|
|
75
|
+
);
|
|
64
76
|
|
|
65
77
|
spinner.stop();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
for await (const part of response) {
|
|
78
|
+
for await (const part of responseStream) {
|
|
69
79
|
process.stdout.write(chalk.white(part.message.content));
|
|
70
80
|
}
|
|
71
81
|
|
|
72
|
-
console.log(chalk.cyan('\n\nAudit complete. Always
|
|
82
|
+
console.log(chalk.cyan('\n\nAudit complete. Always verify AI suggestions.'));
|
|
73
83
|
|
|
74
84
|
} catch (error) {
|
|
75
85
|
spinner.stop();
|
|
@@ -1,11 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FlowDev - Intelligent CLI tool
|
|
3
|
+
* @module flowdev
|
|
4
|
+
* @version 1.0.5
|
|
5
|
+
* * @license MIT
|
|
6
|
+
* Copyright (c) 2026 FlowDev Technologies.
|
|
7
|
+
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
* * The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
*/
|
|
19
|
+
|
|
2
20
|
import chalk from 'chalk';
|
|
3
21
|
import ora from 'ora';
|
|
4
22
|
import fs from 'fs-extra';
|
|
5
23
|
import path from 'path';
|
|
6
24
|
import isBinaryPath from 'is-binary-path';
|
|
7
25
|
import { createRequire } from 'module';
|
|
8
|
-
import {
|
|
26
|
+
import { getAIResponse } from '../../utils/engine-check.js';
|
|
9
27
|
import { logger } from '../../utils/logger.js';
|
|
10
28
|
|
|
11
29
|
const require = createRequire(import.meta.url);
|
|
@@ -38,27 +56,26 @@ export async function explainCommand(filePath) {
|
|
|
38
56
|
const spinner = ora(chalk.cyan('Initializing...')).start();
|
|
39
57
|
|
|
40
58
|
try {
|
|
41
|
-
await ensureEngineReady(spinner, 'llama3');
|
|
42
|
-
|
|
43
59
|
spinner.text = chalk.cyan(`Reading ${path.basename(filePath)}...`);
|
|
44
60
|
const content = await extractText(filePath);
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
62
|
+
|
|
63
|
+
const responseStream = await getAIResponse(
|
|
64
|
+
[{
|
|
65
|
+
role: 'user',
|
|
66
|
+
content: `Explain the following content clearly and concisely:\n\n${content.substring(0, 15000)}`
|
|
67
|
+
}],
|
|
68
|
+
spinner
|
|
69
|
+
);
|
|
55
70
|
|
|
56
71
|
spinner.stop();
|
|
57
72
|
console.log(chalk.red.bold(`ANALYSIS: ${path.basename(filePath).toUpperCase()} `));
|
|
58
73
|
|
|
59
|
-
for await (const part of
|
|
74
|
+
for await (const part of responseStream) {
|
|
60
75
|
process.stdout.write(chalk.white(part.message.content));
|
|
61
76
|
}
|
|
77
|
+
process.stdout.write('\n');
|
|
78
|
+
|
|
62
79
|
} catch (error) {
|
|
63
80
|
spinner.stop();
|
|
64
81
|
logger.error(`Explain error: ${error.message}`);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FlowDev - Intelligent CLI tool
|
|
3
|
+
* @module flowdev
|
|
4
|
+
* @version 1.0.5
|
|
5
|
+
* * @license MIT
|
|
6
|
+
* Copyright (c) 2026 FlowDev Technologies.
|
|
7
|
+
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
* * The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import chalk from 'chalk';
|
|
21
|
+
import ora from 'ora';
|
|
22
|
+
import fs from 'fs-extra';
|
|
23
|
+
import path from 'path';
|
|
24
|
+
import { getAIResponse } from '../../utils/engine-check.js';
|
|
25
|
+
import { logger } from '../../utils/logger.js';
|
|
26
|
+
|
|
27
|
+
export async function readmeCommand() {
|
|
28
|
+
const spinner = ora(chalk.cyan('Reading project structure...')).start();
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const rootDir = process.cwd();
|
|
32
|
+
let projectInfo = "";
|
|
33
|
+
|
|
34
|
+
if (await fs.pathExists(path.join(rootDir, 'package.json'))) {
|
|
35
|
+
const pkg = await fs.readJson(path.join(rootDir, 'package.json'));
|
|
36
|
+
projectInfo += `Type: Node.js, Name: ${pkg.name}, Deps: ${Object.keys(pkg.dependencies || {}).join(', ')}`;
|
|
37
|
+
} else if (await fs.pathExists(path.join(rootDir, 'manage.py'))) {
|
|
38
|
+
projectInfo += `Type: Django/Python project`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const prompt = `
|
|
42
|
+
Generate a professional README.md for a project with these details: ${projectInfo}.
|
|
43
|
+
The README should include:
|
|
44
|
+
- A catchy title with an emoji.
|
|
45
|
+
- Description, Installation, Usage.
|
|
46
|
+
- Return ONLY the markdown content.
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const responseStream = await getAIResponse(
|
|
50
|
+
[{ role: 'user', content: prompt }],
|
|
51
|
+
spinner
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
let readmeContent = "";
|
|
55
|
+
spinner.text = chalk.magenta('Drafting your documentation...');
|
|
56
|
+
|
|
57
|
+
for await (const part of responseStream) {
|
|
58
|
+
readmeContent += part.message.content;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const readmePath = path.join(rootDir, 'README.md');
|
|
62
|
+
await fs.writeFile(readmePath, readmeContent);
|
|
63
|
+
|
|
64
|
+
spinner.succeed(chalk.green('README.md generated successfully!'));
|
|
65
|
+
|
|
66
|
+
} catch (error) {
|
|
67
|
+
spinner.stop();
|
|
68
|
+
logger.error('Failed to generate README: ' + error.message);
|
|
69
|
+
}
|
|
70
|
+
}
|