mantisai-cli 2.0.1 → 2.0.2

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/bin/mantis.js CHANGED
@@ -90,6 +90,9 @@ addMapOptions(create
90
90
  const result = await createCodebaseCsv(root, out, { maxChars: opts.maxChars });
91
91
  success(`Indexed ${result.count} files`);
92
92
  info(`CSV: ${result.outFile}`);
93
+ if (result.skipped?.length) {
94
+ info(`Skipped ${result.skipped.length} binary file(s) (e.g. ${result.skipped.slice(0, 3).join(', ')})`);
95
+ }
93
96
  if (opts.createMap) {
94
97
  const mapResult = await createMapFlow(result.outFile, {
95
98
  ...opts,
@@ -18,6 +18,8 @@ const DEFAULT_IGNORES = [
18
18
  '**/package-lock.json',
19
19
  '**/pnpm-lock.yaml',
20
20
  '**/yarn.lock',
21
+ '**/.DS_Store',
22
+ '**/Thumbs.db',
21
23
  ];
22
24
 
23
25
  const EXT_LANGUAGE = {
@@ -42,6 +44,8 @@ const EXT_LANGUAGE = {
42
44
 
43
45
  const SOURCE_EXTENSIONS = Object.keys(EXT_LANGUAGE);
44
46
 
47
+ const NULL_BYTE = String.fromCharCode(0);
48
+
45
49
  function inferKind(rel) {
46
50
  const base = path.basename(rel).toLowerCase();
47
51
  if (base.includes('test') || base.includes('spec')) return 'test';
@@ -73,8 +77,27 @@ function summarize(content) {
73
77
  return (comment || lines[0] || '').replace(/^\/\/|^#|^\/\*+|^\*|<!--|-->/g, '').trim().slice(0, 240);
74
78
  }
75
79
 
80
+ function isBinaryBuffer(buf) {
81
+ // Postgres JSON/text columns reject the NUL byte (0x00), and other low
82
+ // control bytes are a strong signal of non-text payloads (images,
83
+ // .DS_Store, compiled artifacts). Sniff the head of the file.
84
+ const sample = buf.subarray(0, Math.min(buf.length, 8192));
85
+ for (let i = 0; i < sample.length; i++) {
86
+ const b = sample[i];
87
+ if (b === 0) return true;
88
+ // allow \t (9), \n (10), \r (13); reject other C0 control bytes
89
+ if (b < 9 || (b > 13 && b < 32)) return true;
90
+ }
91
+ return false;
92
+ }
93
+
76
94
  function readText(file, maxChars) {
77
- const raw = fs.readFileSync(file, 'utf8');
95
+ const buf = fs.readFileSync(file);
96
+ if (isBinaryBuffer(buf)) return null;
97
+ let raw = buf.toString('utf8');
98
+ // belt-and-suspenders: strip any NUL chars that survived decoding,
99
+ // since Postgres JSON columns will reject them.
100
+ if (raw.indexOf(NULL_BYTE) !== -1) raw = raw.split(NULL_BYTE).join('');
78
101
  return raw.length > maxChars ? `${raw.slice(0, maxChars)}\n\n[truncated]` : raw;
79
102
  }
80
103
 
@@ -89,12 +112,18 @@ export async function createCodebaseCsv(rootDir, outFile, { maxChars = 12000, in
89
112
  onlyFiles: true,
90
113
  });
91
114
 
92
- const rows = files.sort().map((file) => {
115
+ const skipped = [];
116
+ const rows = [];
117
+ for (const file of files.sort()) {
93
118
  const rel = path.relative(root, file).replace(/\\/g, '/');
94
119
  const ext = path.extname(file).toLowerCase();
95
120
  const content = readText(file, maxChars);
121
+ if (content === null) {
122
+ skipped.push(rel);
123
+ continue;
124
+ }
96
125
  const stat = fs.statSync(file);
97
- return {
126
+ rows.push({
98
127
  path: rel,
99
128
  file_name: path.basename(file),
100
129
  extension: ext.replace(/^\./, ''),
@@ -105,11 +134,11 @@ export async function createCodebaseCsv(rootDir, outFile, { maxChars = 12000, in
105
134
  imports: importsFrom(content),
106
135
  summary: summarize(content),
107
136
  content,
108
- };
109
- });
137
+ });
138
+ }
110
139
 
111
140
  if (!rows.length) throw new Error(`No source files found in ${root}`);
112
141
  fs.mkdirSync(path.dirname(path.resolve(outFile)), { recursive: true });
113
142
  fs.writeFileSync(outFile, stringify(rows, { header: true }));
114
- return { root, outFile: path.resolve(outFile), count: rows.length };
143
+ return { root, outFile: path.resolve(outFile), count: rows.length, skipped };
115
144
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mantisai-cli",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "Mantis developer CLI — create maps, manage spaces and threads, configure Claude Code, and connect agents to Mantis MCP.",
5
5
  "type": "module",
6
6
  "license": "MIT",