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.
Files changed (3) hide show
  1. package/dist/index.js +54 -28
  2. package/package.json +4 -6
  3. 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 (DASHBOARD) ---
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')} Disable auto-backups`);
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: "ChatGPT-5", limit: " 200,000", type: "Large" },
104
- { name: "Claude 4.5 Sonnet", limit: " 200,000", type: "Large" },
105
- { name: "GPT-4o", limit: " 128,000", type: "Medium" },
106
- { name: "Llama 4 405B", limit: " 128,000", type: "Medium" },
107
- { name: "DeepSeek V3", limit: " 128,000", type: "Medium" },
108
- { name: "ChatGPT (Free)", limit: " ~8,000", type: "Small" },
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 (ROBUST) ---
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, // Fixes Windows EPERM crashes
160
- followSymbolicLinks: false // Fixes Infinite Loops
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
- // 2. Check Binary
190
- if (await isBinaryFile(file)) {
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 = await fs.readFile(file, 'utf-8');
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(`\nSECURITY ALERT: Secrets detected in ${file}`));
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
- const tokens = encode(output).length;
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.1",
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>