aidx 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/dist/index.js +54 -28
- 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: "",
|
|
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
|
});
|
|
@@ -98,14 +113,29 @@ program
|
|
|
98
113
|
console.log('\n' + chalk.bold('AI Model Context Limits (2025 Reference)'));
|
|
99
114
|
console.log(chalk.dim('--------------------------------------------------'));
|
|
100
115
|
const models = [
|
|
116
|
+
// HUGE (≈ 1M+ tokens)
|
|
101
117
|
{ name: "Gemini 3 Pro", limit: "2,000,000+", type: "Huge" },
|
|
118
|
+
{ name: "Gemini 2.5 Pro", limit: "1,000,000+", type: "Huge" },
|
|
102
119
|
{ name: "Gemini 2.5 Flash", limit: "1,000,000+", type: "Huge" },
|
|
103
|
-
{ name: "
|
|
104
|
-
{ name: "
|
|
105
|
-
{ name: "
|
|
106
|
-
{ name: "
|
|
107
|
-
|
|
108
|
-
{ name: "ChatGPT
|
|
120
|
+
{ name: "Llama 4 Scout", limit: "1,000,000+", type: "Huge" },
|
|
121
|
+
{ name: "Llama 4 Maverick", limit: "1,000,000+", type: "Huge" },
|
|
122
|
+
{ name: "Qwen 2.5 1M", limit: "1,000,000+", type: "Huge" },
|
|
123
|
+
{ name: "GPT-4.1", limit: "1,000,000+", type: "Huge" },
|
|
124
|
+
// LARGE (≈ 200K–500K tokens)
|
|
125
|
+
{ name: "ChatGPT-5", limit: "200,000+", type: "Large" },
|
|
126
|
+
{ name: "Claude 4.5 Sonnet", limit: "200,000+", type: "Large" },
|
|
127
|
+
{ name: "Claude 4.5 Opus", limit: "200,000+", type: "Large" },
|
|
128
|
+
{ name: "Grok 4", limit: "256,000", type: "Large" },
|
|
129
|
+
{ name: "Cohere Command A", limit: "256,000", type: "Large" },
|
|
130
|
+
// MEDIUM (≈ 100K–150K tokens)
|
|
131
|
+
{ name: "GPT-4o", limit: "128,000", type: "Medium" },
|
|
132
|
+
{ name: "Llama 4 405B", limit: "128,000", type: "Medium" },
|
|
133
|
+
{ name: "DeepSeek V3", limit: "128,000", type: "Medium" },
|
|
134
|
+
{ name: "Grok 3", limit: "128,000", type: "Medium" },
|
|
135
|
+
{ name: "GPT-5 Mini", limit: "128,000", type: "Medium" },
|
|
136
|
+
// SMALL (< 50K tokens)
|
|
137
|
+
{ name: "ChatGPT (Free)", limit: "~8,000", type: "Small" },
|
|
138
|
+
{ name: "Claude Haiku", limit: "~16,000", type: "Small" },
|
|
109
139
|
];
|
|
110
140
|
console.log(chalk.cyan('Model Name'.padEnd(20)) + chalk.yellow('Max Tokens'.padEnd(15)) + chalk.white('Category'));
|
|
111
141
|
console.log(chalk.dim('--------------------------------------------------'));
|
|
@@ -137,7 +167,7 @@ program
|
|
|
137
167
|
console.log(`\nCurrent Backup Status: ${status ? chalk.green('ENABLED') : chalk.red('DISABLED')}`);
|
|
138
168
|
}
|
|
139
169
|
});
|
|
140
|
-
// --- COMMAND: COPY (
|
|
170
|
+
// --- COMMAND: COPY (FAST) ---
|
|
141
171
|
program
|
|
142
172
|
.command('copy')
|
|
143
173
|
.description('Select files and copy to clipboard')
|
|
@@ -145,19 +175,15 @@ program
|
|
|
145
175
|
console.log(chalk.blue('Scanning directory...'));
|
|
146
176
|
const files = await glob(['**/*'], {
|
|
147
177
|
ignore: [
|
|
148
|
-
// Windows System Junk (CRITICAL FOR STABILITY)
|
|
149
178
|
'**/Application Data/**', '**/Cookies/**', '**/Local Settings/**', '**/Recent/**', '**/Start Menu/**',
|
|
150
|
-
// Dev Junk
|
|
151
179
|
'**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.vscode/**',
|
|
152
180
|
'**/__pycache__/**', '**/venv/**', '**/target/**', '**/bin/**', '**/obj/**',
|
|
153
|
-
'**/vendor/**',
|
|
154
|
-
// File Types
|
|
155
|
-
'**/*.lock', '**/*.log', '**/*.png', '**/*.exe', '**/*.dll', '**/*.zip', '**/*.tar', '**/*.gz'
|
|
181
|
+
'**/vendor/**', '**/*.lock', '**/*.log', '**/*.png', '**/*.exe', '**/*.dll', '**/*.zip', '**/*.tar', '**/*.gz'
|
|
156
182
|
],
|
|
157
183
|
onlyFiles: true,
|
|
158
184
|
dot: true,
|
|
159
|
-
suppressErrors: true,
|
|
160
|
-
followSymbolicLinks: false
|
|
185
|
+
suppressErrors: true,
|
|
186
|
+
followSymbolicLinks: false
|
|
161
187
|
});
|
|
162
188
|
if (files.length === 0)
|
|
163
189
|
return console.log(chalk.red('Error: No files found.'));
|
|
@@ -179,23 +205,22 @@ program
|
|
|
179
205
|
console.log(chalk.dim('Reading files...'));
|
|
180
206
|
for (const file of selectedFiles) {
|
|
181
207
|
try {
|
|
182
|
-
// 1. Check Size
|
|
183
208
|
const stats = statSync(file);
|
|
184
209
|
if (stats.size > MAX_FILE_SIZE) {
|
|
185
210
|
console.log(chalk.yellow(`⚠ Skipped large file (>1.5MB): ${file}`));
|
|
186
211
|
skippedCount++;
|
|
187
212
|
continue;
|
|
188
213
|
}
|
|
189
|
-
//
|
|
190
|
-
|
|
214
|
+
// Optimized Read: Read buffer first to check binary, then convert to string
|
|
215
|
+
const buffer = await fs.readFile(file);
|
|
216
|
+
if (isBinary(buffer)) {
|
|
191
217
|
console.log(chalk.yellow(`⚠ Skipped binary file: ${file}`));
|
|
192
218
|
skippedCount++;
|
|
193
219
|
continue;
|
|
194
220
|
}
|
|
195
|
-
const content =
|
|
196
|
-
// 3. Check Secrets
|
|
221
|
+
const content = buffer.toString('utf-8');
|
|
197
222
|
if (file.includes('.env') || SECRET_REGEX.test(content)) {
|
|
198
|
-
console.log(chalk.red(`\
|
|
223
|
+
console.log(chalk.red(`\n🛑 SECURITY ALERT: Secrets detected in ${file}`));
|
|
199
224
|
skippedCount++;
|
|
200
225
|
continue;
|
|
201
226
|
}
|
|
@@ -208,14 +233,15 @@ program
|
|
|
208
233
|
output += XML_SCHEMA_INSTRUCTION;
|
|
209
234
|
try {
|
|
210
235
|
await clipboardy.write(output);
|
|
211
|
-
|
|
236
|
+
// LIGHTWEIGHT TOKENIZER USAGE
|
|
237
|
+
const tokens = estimateTokens(output);
|
|
212
238
|
const finalCount = selectedFiles.length - skippedCount;
|
|
213
239
|
const tokenColor = tokens > 100000 ? chalk.red : tokens > 30000 ? chalk.yellow : chalk.green;
|
|
214
240
|
console.log(chalk.green(`\n✔ Copied ${finalCount} files to clipboard`));
|
|
215
241
|
console.log(`Estimated Tokens: ${tokenColor(tokens.toLocaleString())}`);
|
|
216
242
|
}
|
|
217
243
|
catch (e) {
|
|
218
|
-
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).'));
|
|
219
245
|
console.log(chalk.dim('Try selecting fewer files.'));
|
|
220
246
|
}
|
|
221
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>
|