aidx 1.0.2 → 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/dist/index.js +33 -22
- package/package.json +4 -6
- package/readme.md +5 -5
package/dist/index.js
CHANGED
|
@@ -7,15 +7,13 @@ import { statSync } from 'fs';
|
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import clipboardy from 'clipboardy';
|
|
9
9
|
import chalk from 'chalk';
|
|
10
|
-
import { encode } from 'gpt-tokenizer';
|
|
11
10
|
import * as Diff from 'diff';
|
|
12
|
-
import { isBinaryFile } from 'isbinaryfile';
|
|
13
11
|
// --- CONFIGURATION ---
|
|
14
12
|
const METADATA = {
|
|
15
13
|
name: "aidx",
|
|
16
14
|
description: "A CLI bridge between local code and LLMs.",
|
|
17
15
|
author: "rx76d",
|
|
18
|
-
version: "1.0.
|
|
16
|
+
version: "1.0.3",
|
|
19
17
|
license: "MIT",
|
|
20
18
|
github: "https://github.com/rx76d/aidx"
|
|
21
19
|
};
|
|
@@ -46,6 +44,24 @@ console.log("Full code here...");
|
|
|
46
44
|
</file>
|
|
47
45
|
================================================================
|
|
48
46
|
`;
|
|
47
|
+
// --- UTILS: ZERO-DEPENDENCY HELPERS ---
|
|
48
|
+
// 1. Token Estimator (1 token ~= 4 chars in Code)
|
|
49
|
+
function estimateTokens(text) {
|
|
50
|
+
return Math.ceil(text.length / 4);
|
|
51
|
+
}
|
|
52
|
+
// 2. Binary Detector (Checks for null bytes in first 1KB)
|
|
53
|
+
function isBinary(buffer) {
|
|
54
|
+
// If file is empty, it's text safe
|
|
55
|
+
if (buffer.length === 0)
|
|
56
|
+
return false;
|
|
57
|
+
// Check first 1000 bytes for a null byte (common in images/binaries)
|
|
58
|
+
const len = Math.min(buffer.length, 1000);
|
|
59
|
+
for (let i = 0; i < len; i++) {
|
|
60
|
+
if (buffer[i] === 0x00)
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
49
65
|
// --- GLOBAL HANDLERS ---
|
|
50
66
|
process.on('SIGINT', () => {
|
|
51
67
|
console.log(chalk.yellow('\n\nOperation cancelled by user.'));
|
|
@@ -72,7 +88,7 @@ program
|
|
|
72
88
|
.name(METADATA.name)
|
|
73
89
|
.description(METADATA.description)
|
|
74
90
|
.version(METADATA.version);
|
|
75
|
-
// --- ROOT COMMAND
|
|
91
|
+
// --- ROOT COMMAND ---
|
|
76
92
|
program.action(async () => {
|
|
77
93
|
const backupEnabled = await getBackupStatus();
|
|
78
94
|
console.log('\n' + chalk.bgBlue.bold(` ${METADATA.name.toUpperCase()} `) + chalk.dim(` v${METADATA.version}`));
|
|
@@ -80,13 +96,12 @@ program.action(async () => {
|
|
|
80
96
|
console.log(`${chalk.bold('Description:')} ${METADATA.description}`);
|
|
81
97
|
console.log(`${chalk.bold('Author:')} ${METADATA.author}`);
|
|
82
98
|
console.log(`${chalk.bold('Backups:')} ${backupEnabled ? chalk.green('ENABLED') : chalk.dim('DISABLED')}`);
|
|
83
|
-
console.log(`${chalk.bold('Limit:')} 1.5MB per file`);
|
|
84
99
|
console.log(chalk.dim('----------------------------------------'));
|
|
85
100
|
console.log('\nAvailable Commands:');
|
|
86
101
|
console.log(` ${chalk.cyan('npx aidx copy')} Select files and copy context`);
|
|
87
102
|
console.log(` ${chalk.cyan('npx aidx apply')} Apply AI changes to disk`);
|
|
88
103
|
console.log(` ${chalk.cyan('npx aidx backup --on')} Enable auto-backups`);
|
|
89
|
-
console.log(` ${chalk.cyan('npx aidx backup --off')}
|
|
104
|
+
console.log(` ${chalk.cyan('npx aidx backup --off')} Disable auto-backups`);
|
|
90
105
|
console.log(` ${chalk.cyan('npx aidx stl')} Show AI token limits`);
|
|
91
106
|
console.log(`\nRun ${chalk.gray('npx aidx --help')} for details.\n`);
|
|
92
107
|
});
|
|
@@ -152,7 +167,7 @@ program
|
|
|
152
167
|
console.log(`\nCurrent Backup Status: ${status ? chalk.green('ENABLED') : chalk.red('DISABLED')}`);
|
|
153
168
|
}
|
|
154
169
|
});
|
|
155
|
-
// --- COMMAND: COPY (
|
|
170
|
+
// --- COMMAND: COPY (FAST) ---
|
|
156
171
|
program
|
|
157
172
|
.command('copy')
|
|
158
173
|
.description('Select files and copy to clipboard')
|
|
@@ -160,19 +175,15 @@ program
|
|
|
160
175
|
console.log(chalk.blue('Scanning directory...'));
|
|
161
176
|
const files = await glob(['**/*'], {
|
|
162
177
|
ignore: [
|
|
163
|
-
// Windows System Junk (CRITICAL FOR STABILITY)
|
|
164
178
|
'**/Application Data/**', '**/Cookies/**', '**/Local Settings/**', '**/Recent/**', '**/Start Menu/**',
|
|
165
|
-
// Dev Junk
|
|
166
179
|
'**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.vscode/**',
|
|
167
180
|
'**/__pycache__/**', '**/venv/**', '**/target/**', '**/bin/**', '**/obj/**',
|
|
168
|
-
'**/vendor/**',
|
|
169
|
-
// File Types
|
|
170
|
-
'**/*.lock', '**/*.log', '**/*.png', '**/*.exe', '**/*.dll', '**/*.zip', '**/*.tar', '**/*.gz'
|
|
181
|
+
'**/vendor/**', '**/*.lock', '**/*.log', '**/*.png', '**/*.exe', '**/*.dll', '**/*.zip', '**/*.tar', '**/*.gz'
|
|
171
182
|
],
|
|
172
183
|
onlyFiles: true,
|
|
173
184
|
dot: true,
|
|
174
|
-
suppressErrors: true,
|
|
175
|
-
followSymbolicLinks: false
|
|
185
|
+
suppressErrors: true,
|
|
186
|
+
followSymbolicLinks: false
|
|
176
187
|
});
|
|
177
188
|
if (files.length === 0)
|
|
178
189
|
return console.log(chalk.red('Error: No files found.'));
|
|
@@ -194,23 +205,22 @@ program
|
|
|
194
205
|
console.log(chalk.dim('Reading files...'));
|
|
195
206
|
for (const file of selectedFiles) {
|
|
196
207
|
try {
|
|
197
|
-
// 1. Check Size
|
|
198
208
|
const stats = statSync(file);
|
|
199
209
|
if (stats.size > MAX_FILE_SIZE) {
|
|
200
210
|
console.log(chalk.yellow(`⚠ Skipped large file (>1.5MB): ${file}`));
|
|
201
211
|
skippedCount++;
|
|
202
212
|
continue;
|
|
203
213
|
}
|
|
204
|
-
//
|
|
205
|
-
|
|
214
|
+
// Optimized Read: Read buffer first to check binary, then convert to string
|
|
215
|
+
const buffer = await fs.readFile(file);
|
|
216
|
+
if (isBinary(buffer)) {
|
|
206
217
|
console.log(chalk.yellow(`⚠ Skipped binary file: ${file}`));
|
|
207
218
|
skippedCount++;
|
|
208
219
|
continue;
|
|
209
220
|
}
|
|
210
|
-
const content =
|
|
211
|
-
// 3. Check Secrets
|
|
221
|
+
const content = buffer.toString('utf-8');
|
|
212
222
|
if (file.includes('.env') || SECRET_REGEX.test(content)) {
|
|
213
|
-
console.log(chalk.red(`\
|
|
223
|
+
console.log(chalk.red(`\n🛑 SECURITY ALERT: Secrets detected in ${file}`));
|
|
214
224
|
skippedCount++;
|
|
215
225
|
continue;
|
|
216
226
|
}
|
|
@@ -223,14 +233,15 @@ program
|
|
|
223
233
|
output += XML_SCHEMA_INSTRUCTION;
|
|
224
234
|
try {
|
|
225
235
|
await clipboardy.write(output);
|
|
226
|
-
|
|
236
|
+
// LIGHTWEIGHT TOKENIZER USAGE
|
|
237
|
+
const tokens = estimateTokens(output);
|
|
227
238
|
const finalCount = selectedFiles.length - skippedCount;
|
|
228
239
|
const tokenColor = tokens > 100000 ? chalk.red : tokens > 30000 ? chalk.yellow : chalk.green;
|
|
229
240
|
console.log(chalk.green(`\n✔ Copied ${finalCount} files to clipboard`));
|
|
230
241
|
console.log(`Estimated Tokens: ${tokenColor(tokens.toLocaleString())}`);
|
|
231
242
|
}
|
|
232
243
|
catch (e) {
|
|
233
|
-
console.log(chalk.red('Clipboard write failed (File too large for OS).'));
|
|
244
|
+
console.log(chalk.red('❌ Clipboard write failed (File too large for OS).'));
|
|
234
245
|
console.log(chalk.dim('Try selecting fewer files.'));
|
|
235
246
|
}
|
|
236
247
|
});
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aidx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "A CLI bridge between local code and LLMs. Copy context to clipboard and apply AI changes safely with diffs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"aidx": "dist/index.js"
|
|
8
|
+
"aidx": "./dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
@@ -48,9 +48,7 @@
|
|
|
48
48
|
"clipboardy": "^4.0.0",
|
|
49
49
|
"commander": "^12.0.0",
|
|
50
50
|
"diff": "^5.2.0",
|
|
51
|
-
"fast-glob": "^3.3.2"
|
|
52
|
-
"gpt-tokenizer": "^2.1.2",
|
|
53
|
-
"isbinaryfile": "^5.0.2"
|
|
51
|
+
"fast-glob": "^3.3.2"
|
|
54
52
|
},
|
|
55
53
|
"devDependencies": {
|
|
56
54
|
"@types/diff": "^5.0.9",
|
|
@@ -61,4 +59,4 @@
|
|
|
61
59
|
"engines": {
|
|
62
60
|
"node": ">=18.0.0"
|
|
63
61
|
}
|
|
64
|
-
}
|
|
62
|
+
}
|
package/readme.md
CHANGED
|
@@ -90,25 +90,25 @@ Command Description
|
|
|
90
90
|
|
|
91
91
|
# ✨ Features
|
|
92
92
|
|
|
93
|
-
🛡️ **Security Guard
|
|
93
|
+
🛡️ **Security Guard**:
|
|
94
94
|
Automatically detects and blocks API keys (AWS, OpenAI, Stripe) from being copied to the clipboard. If a file looks like a secret, it is skipped.
|
|
95
95
|
|
|
96
|
-
💾 **Automatic Backups
|
|
96
|
+
💾 **Automatic Backups**:
|
|
97
97
|
Don't trust the AI completely? Turn on backups.
|
|
98
98
|
```npx aidx backup --on```
|
|
99
99
|
Before src/App.tsx is updated, aidx will save a copy to src/App.tsx.bak.
|
|
100
100
|
|
|
101
|
-
🌍 **Universal Support
|
|
101
|
+
🌍 **Universal Support**:
|
|
102
102
|
Works with almost any text-based language:
|
|
103
103
|
Web: TS, JS, HTML, CSS, Svelte, Vue, JSX
|
|
104
104
|
Backend: Python, Go, Rust, Java, C#, PHP
|
|
105
105
|
Config: JSON, YAML, TOML, SQL, Markdown
|
|
106
106
|
Smart Ignores: Automatically ignores node_modules, .git, __pycache__, venv, target, bin, and binary files (.png, .exe).
|
|
107
107
|
|
|
108
|
-
📊 **Token Awareness
|
|
108
|
+
📊 **Token Awareness**:
|
|
109
109
|
Calculates estimated token usage before you paste, so you know if you are about to exceed the limits of GPT-5 or Claude 3.5.
|
|
110
110
|
|
|
111
|
-
🛡️ **License
|
|
111
|
+
🛡️ **License**:
|
|
112
112
|
This project is open source and available under the MIT License.
|
|
113
113
|
<div align="center">
|
|
114
114
|
<sub>Developed by rx76d</sub>
|