Skip to content

Commit a8bae20

Browse files
napoleondclaude
andcommitted
fix(atxp): fix zvec integration bugs and improve memory file collection
Fix three zvec integration bugs: ESM dynamic import not unwrapping CJS default export, wrong indexParams key (type→indexType), and search query being contaminated with flag values. Replace .md-only file filter with gitignore-aware collection of all text files, skip binary files and common directories (node_modules, .git, etc.), and increase file limit to 500. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fc18fec commit a8bae20

File tree

6 files changed

+209
-70
lines changed

6 files changed

+209
-70
lines changed

package-lock.json

Lines changed: 4 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/atxp/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"@atxp/client": "^0.10.5",
3838
"chalk": "^5.3.0",
3939
"fs-extra": "^11.2.0",
40+
"ignore": "^7.0.5",
4041
"inquirer": "^9.2.12",
4142
"jszip": "^3.10.1",
4243
"open": "^9.1.0",

packages/atxp/src/commands/commands.test.ts

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import fs from 'fs';
33
import JSZip from 'jszip';
44
import os from 'os';
55
import path from 'path';
6-
import { collectMdFiles, chunkMarkdown, textToVector } from './memory.js';
6+
import { collectFiles, chunkMarkdown, textToVector } from './memory.js';
77

88
describe('Tool Commands', () => {
99
describe('search command', () => {
@@ -182,25 +182,25 @@ describe('Tool Commands', () => {
182182
fs.rmSync(tmpDir, { recursive: true, force: true });
183183
});
184184

185-
it('should collect .md files and ignore non-.md files', () => {
185+
it('should collect all text files including non-.md files', () => {
186186
fs.writeFileSync(path.join(tmpDir, 'README.md'), '# Hello');
187-
fs.writeFileSync(path.join(tmpDir, 'notes.txt'), 'not included');
187+
fs.writeFileSync(path.join(tmpDir, 'notes.txt'), 'included too');
188188
fs.writeFileSync(path.join(tmpDir, 'config.json'), '{}');
189189

190-
const files = collectMdFiles(tmpDir);
190+
const files = collectFiles(tmpDir);
191+
const paths = files.map(f => f.path).sort();
191192

192-
expect(files).toHaveLength(1);
193-
expect(files[0].path).toBe('README.md');
194-
expect(files[0].content).toBe('# Hello');
193+
expect(files).toHaveLength(3);
194+
expect(paths).toEqual(['README.md', 'config.json', 'notes.txt']);
195195
});
196196

197-
it('should collect .md files recursively from subdirectories', () => {
197+
it('should collect files recursively from subdirectories', () => {
198198
const subDir = path.join(tmpDir, 'memory');
199199
fs.mkdirSync(subDir);
200200
fs.writeFileSync(path.join(tmpDir, 'SOUL.md'), '# Soul');
201201
fs.writeFileSync(path.join(subDir, 'session.md'), '# Session');
202202

203-
const files = collectMdFiles(tmpDir);
203+
const files = collectFiles(tmpDir);
204204
const paths = files.map(f => f.path).sort();
205205

206206
expect(paths).toEqual(['SOUL.md', path.join('memory', 'session.md')]);
@@ -211,24 +211,52 @@ describe('Tool Commands', () => {
211211
fs.mkdirSync(deep, { recursive: true });
212212
fs.writeFileSync(path.join(deep, 'deep.md'), 'deep');
213213

214-
const files = collectMdFiles(tmpDir);
214+
const files = collectFiles(tmpDir);
215215

216216
expect(files).toHaveLength(1);
217217
expect(files[0].path).toBe(path.join('a', 'b', 'c', 'deep.md'));
218218
});
219219

220-
it('should return empty array for directory with no .md files', () => {
221-
fs.writeFileSync(path.join(tmpDir, 'file.txt'), 'text');
222-
fs.writeFileSync(path.join(tmpDir, 'data.json'), '{}');
220+
it('should return empty array for empty directory', () => {
221+
const files = collectFiles(tmpDir);
222+
expect(files).toHaveLength(0);
223+
});
223224

224-
const files = collectMdFiles(tmpDir);
225+
it('should skip node_modules and .git directories', () => {
226+
fs.writeFileSync(path.join(tmpDir, 'index.ts'), 'console.log("hi")');
227+
fs.mkdirSync(path.join(tmpDir, 'node_modules', 'pkg'), { recursive: true });
228+
fs.writeFileSync(path.join(tmpDir, 'node_modules', 'pkg', 'index.js'), 'module.exports = {}');
229+
fs.mkdirSync(path.join(tmpDir, '.git', 'objects'), { recursive: true });
230+
fs.writeFileSync(path.join(tmpDir, '.git', 'HEAD'), 'ref: refs/heads/main');
225231

226-
expect(files).toHaveLength(0);
232+
const files = collectFiles(tmpDir);
233+
234+
expect(files).toHaveLength(1);
235+
expect(files[0].path).toBe('index.ts');
227236
});
228237

229-
it('should return empty array for empty directory', () => {
230-
const files = collectMdFiles(tmpDir);
231-
expect(files).toHaveLength(0);
238+
it('should respect .gitignore rules', () => {
239+
fs.writeFileSync(path.join(tmpDir, '.gitignore'), 'secret.env\nlogs/\n');
240+
fs.writeFileSync(path.join(tmpDir, 'app.ts'), 'const x = 1');
241+
fs.writeFileSync(path.join(tmpDir, 'secret.env'), 'API_KEY=abc');
242+
fs.mkdirSync(path.join(tmpDir, 'logs'));
243+
fs.writeFileSync(path.join(tmpDir, 'logs', 'app.log'), 'log entry');
244+
245+
const files = collectFiles(tmpDir);
246+
const paths = files.map(f => f.path).sort();
247+
248+
expect(paths).toEqual(['.gitignore', 'app.ts']);
249+
});
250+
251+
it('should skip binary files', () => {
252+
fs.writeFileSync(path.join(tmpDir, 'readme.md'), '# Hello');
253+
// Write a file with null bytes (binary)
254+
fs.writeFileSync(path.join(tmpDir, 'image.png'), Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x00, 0x00]));
255+
256+
const files = collectFiles(tmpDir);
257+
258+
expect(files).toHaveLength(1);
259+
expect(files[0].path).toBe('readme.md');
232260
});
233261

234262
it('should validate --path is required for push/pull', () => {
@@ -254,7 +282,7 @@ describe('Tool Commands', () => {
254282
fs.mkdirSync(subDir);
255283
fs.writeFileSync(path.join(subDir, 'session.md'), '# Session notes');
256284

257-
const files = collectMdFiles(tmpDir);
285+
const files = collectFiles(tmpDir);
258286

259287
const zip = new JSZip();
260288
for (const file of files) {
@@ -274,7 +302,7 @@ describe('Tool Commands', () => {
274302
fs.mkdirSync(subDir);
275303
fs.writeFileSync(path.join(subDir, 'log.md'), '## Log\n- Entry 1\n- Entry 2');
276304

277-
const files = collectMdFiles(tmpDir);
305+
const files = collectFiles(tmpDir);
278306

279307
// Create zip
280308
const zip = new JSZip();
@@ -300,7 +328,7 @@ describe('Tool Commands', () => {
300328
const repeatedContent = '# Memory\n\n' + 'This is a repeated line of memory content.\n'.repeat(100);
301329
fs.writeFileSync(path.join(tmpDir, 'MEMORY.md'), repeatedContent);
302330

303-
const files = collectMdFiles(tmpDir);
331+
const files = collectFiles(tmpDir);
304332
const jsonSize = Buffer.byteLength(JSON.stringify({ files }), 'utf-8');
305333

306334
const zip = new JSZip();

0 commit comments

Comments
 (0)