nodewise 1.0.1 → 1.0.3
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/README.md +3 -0
- package/bin/nodewise.js +4 -3
- package/logo.png +0 -0
- package/package.json +3 -4
- package/src/config.js +38 -3
- package/src/explainer/interactive.js +111 -22
- package/src/runner.js +12 -6
- package/USER_MANUAL.md +0 -106
package/README.md
CHANGED
|
@@ -71,6 +71,9 @@ Traditional error messages can be cryptic, long, or stacked with irrelevant inte
|
|
|
71
71
|
|
|
72
72
|
## 📋 Example Output
|
|
73
73
|
|
|
74
|
+
<img width="1836" height="694" alt="Screenshot 2026-02-15 223424" src="https://github.com/user-attachments/assets/412f60cf-5ab6-4662-8a0a-1f92145f2485" />
|
|
75
|
+
|
|
76
|
+
|
|
74
77
|
✦ GEMINI INTELLIGENCE
|
|
75
78
|
─────────────────────────────────────────────
|
|
76
79
|
|
package/bin/nodewise.js
CHANGED
|
@@ -26,7 +26,7 @@ function parseArgs() {
|
|
|
26
26
|
setup: false,
|
|
27
27
|
reset: false
|
|
28
28
|
};
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
let scriptPath = null;
|
|
31
31
|
const scriptArgs = [];
|
|
32
32
|
|
|
@@ -78,13 +78,14 @@ ${chalk.bold('MODES')}
|
|
|
78
78
|
${chalk.cyan('Normal Detection')} - Pattern-based error detection (offline)
|
|
79
79
|
|
|
80
80
|
${chalk.bold('CONFIGURATION')}
|
|
81
|
-
Settings are saved in ${chalk.yellow('nodewise.config.json')}
|
|
81
|
+
Settings are saved in ${chalk.yellow('node_modules/.nodewise.config.json')} (if available)
|
|
82
|
+
or ${chalk.yellow('.nodewise.config.json')} in your project root.
|
|
83
|
+
This ensures your API keys are not accidentally committed to version control.
|
|
82
84
|
|
|
83
85
|
${chalk.bold('DOCUMENTATION')}
|
|
84
86
|
https://github.com/yourusername/nodewise
|
|
85
87
|
`);
|
|
86
88
|
}
|
|
87
|
-
|
|
88
89
|
/**
|
|
89
90
|
* Display version
|
|
90
91
|
*/
|
package/logo.png
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodewise",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Node.js error explainer with AI-powered clarity",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"author": "Gourab Das",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"inquirer": "^9.2.15",
|
|
26
25
|
"axios": "^1.6.5",
|
|
26
|
+
"chalk": "^4.1.2",
|
|
27
27
|
"chokidar": "^3.5.3",
|
|
28
|
-
"
|
|
28
|
+
"inquirer": "^9.2.15"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"bin",
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
"url": "https://github.com/Gourab2005/nodewise/issues"
|
|
45
45
|
},
|
|
46
46
|
"homepage": "https://github.com/Gourab2005/nodewise#readme",
|
|
47
|
-
"devDependencies": {},
|
|
48
47
|
"engines": {
|
|
49
48
|
"node": ">=18.0.0"
|
|
50
49
|
}
|
package/src/config.js
CHANGED
|
@@ -9,13 +9,47 @@ const fs = require('fs');
|
|
|
9
9
|
const path = require('path');
|
|
10
10
|
|
|
11
11
|
const CONFIG_FILE = 'nodewise.config.json';
|
|
12
|
+
const HIDDEN_CONFIG_FILE = '.nodewise.config.json';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Get the configuration file path
|
|
15
|
-
*
|
|
16
|
+
* Prioritizes node_modules to avoid accidental git commits
|
|
16
17
|
*/
|
|
17
18
|
function getConfigPath() {
|
|
18
|
-
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const nodeModulesPath = path.join(cwd, 'node_modules');
|
|
21
|
+
const nodeModulesConfig = path.join(nodeModulesPath, HIDDEN_CONFIG_FILE);
|
|
22
|
+
const rootHiddenConfig = path.join(cwd, HIDDEN_CONFIG_FILE);
|
|
23
|
+
const rootLegacyConfig = path.join(cwd, CONFIG_FILE);
|
|
24
|
+
|
|
25
|
+
// 1. Check if config already exists in node_modules
|
|
26
|
+
if (fs.existsSync(nodeModulesConfig)) {
|
|
27
|
+
return nodeModulesConfig;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Check if hidden config exists in root
|
|
31
|
+
if (fs.existsSync(rootHiddenConfig)) {
|
|
32
|
+
return rootHiddenConfig;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 3. Check if legacy config exists in root
|
|
36
|
+
if (fs.existsSync(rootLegacyConfig)) {
|
|
37
|
+
return rootLegacyConfig;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 4. For NEW configs:
|
|
41
|
+
// If node_modules exists, use it (recommended for security)
|
|
42
|
+
if (fs.existsSync(nodeModulesPath)) {
|
|
43
|
+
try {
|
|
44
|
+
// Ensure node_modules exists (redundant but safe)
|
|
45
|
+
return nodeModulesConfig;
|
|
46
|
+
} catch (e) {
|
|
47
|
+
// Fallback to root if node_modules is not writable
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Final fallback to hidden root config
|
|
52
|
+
return rootHiddenConfig;
|
|
19
53
|
}
|
|
20
54
|
|
|
21
55
|
/**
|
|
@@ -163,5 +197,6 @@ module.exports = {
|
|
|
163
197
|
mergeWithDefaults,
|
|
164
198
|
createConfig,
|
|
165
199
|
updateConfig,
|
|
166
|
-
CONFIG_FILE
|
|
200
|
+
CONFIG_FILE,
|
|
201
|
+
HIDDEN_CONFIG_FILE
|
|
167
202
|
};
|
|
@@ -8,7 +8,14 @@ const chalk = require('chalk');
|
|
|
8
8
|
const readline = require('readline');
|
|
9
9
|
const { explain } = require('./index');
|
|
10
10
|
|
|
11
|
+
// Global state for cancellation
|
|
12
|
+
let cancelPrompt = false;
|
|
13
|
+
let activePromptResolver = null;
|
|
14
|
+
|
|
11
15
|
async function showInteractiveExplainer(errorText, config) {
|
|
16
|
+
// Reset cancel flag
|
|
17
|
+
cancelPrompt = false;
|
|
18
|
+
|
|
12
19
|
console.log('\n');
|
|
13
20
|
const summary = (errorText || '').toString().split('\n')[0] || 'Unknown error';
|
|
14
21
|
|
|
@@ -20,34 +27,105 @@ async function showInteractiveExplainer(errorText, config) {
|
|
|
20
27
|
console.log(chalk.white(' ' + summary));
|
|
21
28
|
console.log();
|
|
22
29
|
|
|
23
|
-
// Compact, modern prompt
|
|
24
|
-
console.log(chalk.cyan.bold(' ? ') + chalk.white('Would you like an AI explanation?'));
|
|
25
|
-
console.log(chalk.gray(' [y] Yes, explain it [n] No, just skip'));
|
|
26
|
-
console.log();
|
|
27
|
-
|
|
28
30
|
const answer = await getUserInput();
|
|
29
31
|
|
|
30
|
-
if (answer
|
|
32
|
+
if (answer === 'yes') {
|
|
31
33
|
await explainErrorInteractively(errorText, config);
|
|
34
|
+
} else if (answer === 'cancelled') {
|
|
35
|
+
// Silently skip on cancellation
|
|
32
36
|
} else {
|
|
33
37
|
console.log(chalk.gray(' Skipped.\n'));
|
|
34
38
|
}
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
function getUserInput() {
|
|
41
|
+
async function getUserInput() {
|
|
38
42
|
return new Promise((resolve) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
const options = [
|
|
44
|
+
{ label: chalk.green('✓ Yes, explain it'), value: 'yes' },
|
|
45
|
+
{ label: chalk.gray('✗ No, just skip'), value: 'no' }
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
let selectedIndex = 0;
|
|
49
|
+
let isResolved = false;
|
|
50
|
+
|
|
51
|
+
// Store resolver for cancellation
|
|
52
|
+
activePromptResolver = () => {
|
|
53
|
+
if (!isResolved) {
|
|
54
|
+
cleanup();
|
|
55
|
+
isResolved = true;
|
|
56
|
+
resolve('cancelled');
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Display the question
|
|
61
|
+
console.log(chalk.cyan(' ? ') + chalk.white('Would you like an AI explanation?'));
|
|
62
|
+
|
|
63
|
+
const renderOptions = () => {
|
|
64
|
+
options.forEach((option, index) => {
|
|
65
|
+
const prefix = index === selectedIndex ? chalk.cyan('❯ ') : ' ';
|
|
66
|
+
console.log(` ${prefix}${option.label}`);
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const cleanup = () => {
|
|
71
|
+
process.stdin.removeListener('keypress', onKeypress);
|
|
72
|
+
if (process.stdin.isTTY) {
|
|
73
|
+
process.stdin.setRawMode(false);
|
|
74
|
+
}
|
|
75
|
+
process.stdin.pause();
|
|
76
|
+
activePromptResolver = null;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Initial render
|
|
80
|
+
renderOptions();
|
|
81
|
+
|
|
82
|
+
// Setup readline for keypress
|
|
83
|
+
readline.emitKeypressEvents(process.stdin);
|
|
84
|
+
if (process.stdin.isTTY) {
|
|
85
|
+
process.stdin.setRawMode(true);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const onKeypress = (str, key) => {
|
|
89
|
+
// Check if cancelled
|
|
90
|
+
if (cancelPrompt) {
|
|
91
|
+
cleanup();
|
|
92
|
+
if (!isResolved) {
|
|
93
|
+
isResolved = true;
|
|
94
|
+
console.log(chalk.yellow('\n (Skipped due to restart)\n'));
|
|
95
|
+
resolve('cancelled');
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (key.name === 'up') {
|
|
101
|
+
// Clear previous options
|
|
102
|
+
process.stdout.write('\x1b[' + options.length + 'A'); // Move cursor up
|
|
103
|
+
process.stdout.write('\x1b[0J'); // Clear from cursor down
|
|
104
|
+
|
|
105
|
+
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : options.length - 1;
|
|
106
|
+
renderOptions();
|
|
107
|
+
} else if (key.name === 'down') {
|
|
108
|
+
// Clear previous options
|
|
109
|
+
process.stdout.write('\x1b[' + options.length + 'A'); // Move cursor up
|
|
110
|
+
process.stdout.write('\x1b[0J'); // Clear from cursor down
|
|
111
|
+
|
|
112
|
+
selectedIndex = selectedIndex < options.length - 1 ? selectedIndex + 1 : 0;
|
|
113
|
+
renderOptions();
|
|
114
|
+
} else if (key.name === 'return') {
|
|
115
|
+
cleanup();
|
|
116
|
+
if (!isResolved) {
|
|
117
|
+
isResolved = true;
|
|
118
|
+
console.log(); // Add newline after selection
|
|
119
|
+
resolve(options[selectedIndex].value);
|
|
120
|
+
}
|
|
121
|
+
} else if (key.ctrl && key.name === 'c') {
|
|
122
|
+
cleanup();
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
process.stdin.on('keypress', onKeypress);
|
|
128
|
+
process.stdin.resume();
|
|
51
129
|
});
|
|
52
130
|
}
|
|
53
131
|
|
|
@@ -69,6 +147,16 @@ function clearThinking(interval) {
|
|
|
69
147
|
process.stdout.write('\r' + ' '.repeat(50) + '\r');
|
|
70
148
|
}
|
|
71
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Cancel any active prompt
|
|
152
|
+
*/
|
|
153
|
+
function cancelActivePrompt() {
|
|
154
|
+
cancelPrompt = true;
|
|
155
|
+
if (activePromptResolver) {
|
|
156
|
+
activePromptResolver();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
72
160
|
function displayExplanation(explanation) {
|
|
73
161
|
console.log('\n');
|
|
74
162
|
|
|
@@ -87,12 +175,12 @@ function displayExplanation(explanation) {
|
|
|
87
175
|
|
|
88
176
|
// High-end minimalist styling
|
|
89
177
|
// If it starts with a keyword, add a line break before it to create gaps between sections
|
|
90
|
-
if (/^(Summary|Problem|Cause|Solution|Fix|Where|Why|File|Line|Note|Suggestion):/i.test(content)) {
|
|
178
|
+
if (/^(Summary|Problem|Cause|Solution|Fix|Where|Why|File|Line|Note|Suggestion|Minimal code fix|Code):/i.test(content)) {
|
|
91
179
|
console.log();
|
|
92
180
|
}
|
|
93
181
|
|
|
94
182
|
content = content
|
|
95
|
-
.replace(/^(Summary|Problem|Cause|Solution|Fix|Where|Why|File|Line|Note|Suggestion):/i, (match) => chalk.hex('#FFAF00').bold(match))
|
|
183
|
+
.replace(/^(Summary|Problem|Cause|Solution|Fix|Where|Why|File|Line|Note|Suggestion|Minimal code fix|Code):/i, (match) => chalk.hex('#FFAF00').bold(match))
|
|
96
184
|
.replace(/`([^`]+)`/g, (match) => chalk.hex('#00FF87')(match))
|
|
97
185
|
.replace(/'([^']+)'/g, (match) => chalk.hex('#00FF87')(match));
|
|
98
186
|
|
|
@@ -119,5 +207,6 @@ async function explainErrorInteractively(errorText, config) {
|
|
|
119
207
|
|
|
120
208
|
module.exports = {
|
|
121
209
|
showInteractiveExplainer,
|
|
122
|
-
displayExplanation
|
|
210
|
+
displayExplanation,
|
|
211
|
+
cancelActivePrompt
|
|
123
212
|
};
|
package/src/runner.js
CHANGED
|
@@ -12,7 +12,7 @@ const { spawn } = require('child_process');
|
|
|
12
12
|
const chokidar = require('chokidar');
|
|
13
13
|
const chalk = require('chalk');
|
|
14
14
|
const { explain } = require('./explainer');
|
|
15
|
-
const { showInteractiveExplainer } = require('./explainer/interactive');
|
|
15
|
+
const { showInteractiveExplainer, cancelActivePrompt } = require('./explainer/interactive');
|
|
16
16
|
|
|
17
17
|
class Runner {
|
|
18
18
|
constructor(scriptPath, args = [], config = {}) {
|
|
@@ -57,7 +57,7 @@ class Runner {
|
|
|
57
57
|
const text = data.toString();
|
|
58
58
|
process.stderr.write(text);
|
|
59
59
|
errorBuffer += text;
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
// Detect errors in stderr and explain them immediately
|
|
62
62
|
if (this.isErrorOutput(text)) {
|
|
63
63
|
this.explainErrorWithDebounce(text);
|
|
@@ -85,7 +85,7 @@ class Runner {
|
|
|
85
85
|
|
|
86
86
|
this.child.on('exit', (code, signal) => {
|
|
87
87
|
this.isProcessExiting = true;
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
if (code !== 0 && code !== null) {
|
|
90
90
|
// Process exited with error
|
|
91
91
|
if (!this.isRestarting && errorBuffer) {
|
|
@@ -148,15 +148,18 @@ class Runner {
|
|
|
148
148
|
|
|
149
149
|
this.isRestarting = true;
|
|
150
150
|
|
|
151
|
+
// Cancel any active interactive prompt
|
|
152
|
+
cancelActivePrompt();
|
|
153
|
+
|
|
151
154
|
if (this.child) {
|
|
152
155
|
this.child.kill('SIGTERM');
|
|
153
|
-
|
|
156
|
+
|
|
154
157
|
// Wait a bit for graceful shutdown
|
|
155
158
|
setTimeout(() => {
|
|
156
159
|
if (this.child && !this.child.killed) {
|
|
157
160
|
this.child.kill('SIGKILL');
|
|
158
161
|
}
|
|
159
|
-
|
|
162
|
+
|
|
160
163
|
setTimeout(() => {
|
|
161
164
|
this.isRestarting = false;
|
|
162
165
|
if (reason) {
|
|
@@ -175,6 +178,9 @@ class Runner {
|
|
|
175
178
|
* Stop the process and watcher
|
|
176
179
|
*/
|
|
177
180
|
stop() {
|
|
181
|
+
// Cancel any active interactive prompt
|
|
182
|
+
cancelActivePrompt();
|
|
183
|
+
|
|
178
184
|
if (this.watcher) {
|
|
179
185
|
this.watcher.close();
|
|
180
186
|
this.watcher = null;
|
|
@@ -228,7 +234,7 @@ class Runner {
|
|
|
228
234
|
return;
|
|
229
235
|
}
|
|
230
236
|
this.lastErrorExplanationTime = now;
|
|
231
|
-
|
|
237
|
+
|
|
232
238
|
// Don't explain startup errors that already caused process exit
|
|
233
239
|
if (this.isProcessExiting) {
|
|
234
240
|
return;
|
package/USER_MANUAL.md
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# 📖 NodeWise User Manual
|
|
2
|
-
|
|
3
|
-
Welcome to **NodeWise**, your AI-powered companion for Node.js development. This manual will help you get the most out of NodeWise's error explanation and auto-restart features.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🚀 Getting Started
|
|
8
|
-
|
|
9
|
-
NodeWise is designed to be a drop-in replacement for `node` or `nodemon` during development.
|
|
10
|
-
|
|
11
|
-
### Installation
|
|
12
|
-
If you haven't already, you can link it globally or install it in your project:
|
|
13
|
-
```bash
|
|
14
|
-
# Link for local development
|
|
15
|
-
npm link
|
|
16
|
-
|
|
17
|
-
# Install as a dev dependency
|
|
18
|
-
npm install -D nodewise
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### Initial Setup
|
|
22
|
-
The first time you run NodeWise, it will launch a setup wizard to configure your preferred explanation mode.
|
|
23
|
-
```bash
|
|
24
|
-
npx nodewise --setup
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## 🤖 Explanation Modes
|
|
30
|
-
|
|
31
|
-
### 1. Gemini Explainer (AI-Powered)
|
|
32
|
-
The "Top-G" mode. It uses Google's latest Gemini models to analyze your specific code and provide context-aware fixes.
|
|
33
|
-
|
|
34
|
-
* **Setup**: Requires a free Gemini API Key from [Google AI Studio](https://aistudio.google.com/app/apikey).
|
|
35
|
-
* **Best for**: Complex logic errors, obscure Node.js core errors, and step-by-step fix guides.
|
|
36
|
-
* **Features**: Beautiful minimalist terminal output with neon highlighting.
|
|
37
|
-
|
|
38
|
-
### 2. Normal Detection (Offline)
|
|
39
|
-
A lightning-fast, pattern-based mode that works entirely offline.
|
|
40
|
-
|
|
41
|
-
* **Setup**: No setup required.
|
|
42
|
-
* **Best for**: Common errors like `MODULE_NOT_FOUND`, `TypeError`, and `ReferenceError`.
|
|
43
|
-
* **Features**: Zero latency, works without an internet connection.
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## ⌨️ Command Line Interface
|
|
48
|
-
|
|
49
|
-
| Command | Description |
|
|
50
|
-
| :--- | :--- |
|
|
51
|
-
| `nodewise <script.js>` | Run a script with auto-restart and error explainer. |
|
|
52
|
-
| `nodewise --setup` | Change modes or update your Gemini API key. |
|
|
53
|
-
| `nodewise --reset` | Wipe configuration and start fresh. |
|
|
54
|
-
| `nodewise --help` | Show available options and examples. |
|
|
55
|
-
| `nodewise -v` | Check your current NodeWise version. |
|
|
56
|
-
|
|
57
|
-
### Running with Arguments
|
|
58
|
-
You can pass arguments to your script just like you would with node:
|
|
59
|
-
```bash
|
|
60
|
-
nodewise server.js --port 3000 --env production
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## ⚙️ Configuration
|
|
66
|
-
NodeWise saves your preferences in `nodewise.config.json` in your project root.
|
|
67
|
-
|
|
68
|
-
```json
|
|
69
|
-
{
|
|
70
|
-
"mode": "gemini",
|
|
71
|
-
"gemini": {
|
|
72
|
-
"apiKey": "YOUR_KEY_HERE"
|
|
73
|
-
},
|
|
74
|
-
"autoRestart": true,
|
|
75
|
-
"ignorePatterns": ["node_modules", ".git"],
|
|
76
|
-
"timeout": 60000
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
* **autoRestart**: Set to `false` if you don't want the process to restart on file changes.
|
|
81
|
-
* **timeout**: Increase this if the AI is taking too long to respond on slow connections.
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## ✨ Pro Tips
|
|
86
|
-
|
|
87
|
-
### 1. Minimalist AI Insight
|
|
88
|
-
When a crash occurs in Gemini mode, you'll see a clean, gapped output. We've removed bulky boxes to keep your terminal clean. Look for the **✦ GEMINI INTELLIGENCE** header.
|
|
89
|
-
|
|
90
|
-
### 2. Auto-Restart
|
|
91
|
-
NodeWise watches your `.js` and `.json` files. As soon as you save a fix, NodeWise will instantly restart your application, allowing for a rapid "Code-Crash-Fix-Repeat" cycle.
|
|
92
|
-
|
|
93
|
-
### 3. Graceful Exit
|
|
94
|
-
Use `Ctrl+C` to shut down both your application and the NodeWise watcher gracefully.
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## 🆘 Troubleshooting
|
|
99
|
-
|
|
100
|
-
* **API Timeouts**: If you see "Gemini timed out," check your internet connection or increase the `timeout` in `nodewise.config.json`.
|
|
101
|
-
* **Invalid Key**: Ensure your API key is correct by re-running `nodewise --setup`.
|
|
102
|
-
* **Files not watching**: Ensure the directory you are working in doesn't have an ignore pattern matching your files.
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
*Made with ❤️ for Node.js developers.*
|