openzoo 0.11.1 → 0.11.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/lib/bindpath.js +47 -2
- package/package.json +1 -1
package/lib/bindpath.js
CHANGED
|
@@ -38,6 +38,35 @@ const DEFAULT_EXTS = [
|
|
|
38
38
|
|
|
39
39
|
const SKIP_DIRS = new Set(['node_modules', '.git', 'target', 'dist', 'build', '.next', '__pycache__', '.venv']);
|
|
40
40
|
|
|
41
|
+
/** Refuse rather than grind. A directory of exports can be hundreds of MB;
|
|
42
|
+
* binding that takes many minutes and mostly buys markup. Raise deliberately. */
|
|
43
|
+
export const MAX_TOTAL_BYTES = Number(process.env.OPENZOO_BIND_MAX_BYTES || 32 * 1024 * 1024);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* HTML → readable text. Chat/forum exports are ~90% markup: binding the raw
|
|
47
|
+
* pages wastes the corpus on tags and makes retrieval rank div soup against
|
|
48
|
+
* the question. Deliberately crude (no parser dependency) but it keeps the
|
|
49
|
+
* text nodes in document order, which is all retrieval needs.
|
|
50
|
+
*/
|
|
51
|
+
export function stripHtml(html) {
|
|
52
|
+
return html
|
|
53
|
+
.replace(/<(script|style)\b[^>]*>[\s\S]*?<\/\1>/gi, ' ')
|
|
54
|
+
.replace(/<!--[\s\S]*?-->/g, ' ')
|
|
55
|
+
.replace(/<br\s*\/?>/gi, '\n')
|
|
56
|
+
.replace(/<\/(p|div|li|tr|h[1-6])>/gi, '\n')
|
|
57
|
+
.replace(/<[^>]+>/g, ' ')
|
|
58
|
+
.replace(/ /g, ' ').replace(/&/g, '&').replace(/</g, '<')
|
|
59
|
+
.replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'")
|
|
60
|
+
.replace(/[ \t]+/g, ' ')
|
|
61
|
+
.replace(/\n\s*\n\s*\n+/g, '\n\n')
|
|
62
|
+
.trim();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const readAsText = (file) => {
|
|
66
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
67
|
+
return /\.html?$/i.test(file) ? stripHtml(raw) : raw;
|
|
68
|
+
};
|
|
69
|
+
|
|
41
70
|
/** Every bindable file under `root` (or just `root` if it is a file). */
|
|
42
71
|
export function collectFiles(root, { exts = DEFAULT_EXTS, maxFiles = 5000 } = {}) {
|
|
43
72
|
const st = fs.statSync(root);
|
|
@@ -109,11 +138,27 @@ export async function bindPath(target, { exts, onProgress, force = false } = {})
|
|
|
109
138
|
const files = collectFiles(resolved, exts ? { exts } : {});
|
|
110
139
|
if (!files.length) throw new Error(`nothing bindable under ${resolved} (looked for text-like files)`);
|
|
111
140
|
|
|
141
|
+
// Size the job BEFORE reading anything. A 2GB export folder is 100MB of
|
|
142
|
+
// text-like files, and silently grinding through it for minutes reads as a
|
|
143
|
+
// hang — an actionable refusal is better than a spinner.
|
|
144
|
+
const onDisk = files.reduce((n, f) => n + fs.statSync(f).size, 0);
|
|
145
|
+
if (onDisk > MAX_TOTAL_BYTES) {
|
|
146
|
+
const biggest = files
|
|
147
|
+
.map((f) => ({ f, size: fs.statSync(f).size }))
|
|
148
|
+
.sort((a, b) => b.size - a.size).slice(0, 3)
|
|
149
|
+
.map(({ f, size }) => `${path.basename(f)} (${(size / 1048576).toFixed(1)}MB)`);
|
|
150
|
+
throw new Error(
|
|
151
|
+
`${(onDisk / 1048576).toFixed(0)}MB across ${files.length} files exceeds the ${(MAX_TOTAL_BYTES / 1048576).toFixed(0)}MB bind limit. `
|
|
152
|
+
+ `Largest: ${biggest.join(', ')}. Point at one file, narrow with --ext/ext, `
|
|
153
|
+
+ `or raise OPENZOO_BIND_MAX_BYTES if you really want all of it.`,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
112
157
|
// Each file is prefixed with its path so retrieval can cite where a passage
|
|
113
158
|
// came from — a corpus of concatenated files with no provenance is much
|
|
114
|
-
// less useful to answer from.
|
|
159
|
+
// less useful to answer from. HTML is reduced to its text (see readAsText).
|
|
115
160
|
const text = files
|
|
116
|
-
.map((f) => `===== ${path.relative(path.dirname(resolved), f) || path.basename(f)} =====\n${
|
|
161
|
+
.map((f) => `===== ${path.relative(path.dirname(resolved), f) || path.basename(f)} =====\n${readAsText(f)}`)
|
|
117
162
|
.join('\n\n');
|
|
118
163
|
|
|
119
164
|
const bytes = Buffer.byteLength(text);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|