@melaya/runner 1.0.41 → 1.0.43

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 (2) hide show
  1. package/dist/pythonEnv.js +58 -0
  2. package/package.json +1 -1
package/dist/pythonEnv.js CHANGED
@@ -170,8 +170,62 @@ function runProc(cmd, args, onLine, envExtra = {}) {
170
170
  child.on("error", () => resolve(1));
171
171
  });
172
172
  }
173
+ /**
174
+ * Idempotent: ensures NLTK's tokenizer data is present in ~/nltk_data so
175
+ * agentscope.rag readers (default split_by="sentence") can chunk without
176
+ * silently failing. Safe to call on every runner launch — the downloader
177
+ * skips packages that are already present and finishes in <100ms.
178
+ *
179
+ * Why this is outside the venv-rebuild guard: previously this was only
180
+ * triggered when PIP_DEPS changed, so any runner box that already had a
181
+ * matching marker would skip the download. Result: Mode B ingest failed
182
+ * with `Resource 'punkt_tab' not found` for every file. Moving it here
183
+ * makes it self-healing on every invocation.
184
+ */
185
+ async function ensureNltkData(onProgress) {
186
+ if (!existsSync(venvPython()))
187
+ return; // venv not built yet, will get caught later
188
+ const pyCode = [
189
+ "import sys, os",
190
+ "try:",
191
+ " import nltk",
192
+ "except ImportError:",
193
+ " print('nltk_missing'); sys.exit(0)",
194
+ "needed = ['punkt', 'punkt_tab']",
195
+ "missing = []",
196
+ "for p in needed:",
197
+ " try: nltk.data.find(f'tokenizers/{p}')",
198
+ " except LookupError: missing.append(p)",
199
+ "if not missing:",
200
+ " print('nltk_data_ok'); sys.exit(0)",
201
+ "print('downloading: ' + ', '.join(missing))",
202
+ "ok_all = True",
203
+ "for p in missing:",
204
+ " try:",
205
+ " if not nltk.download(p, quiet=True):",
206
+ " ok_all = False",
207
+ " print(f'nltk.download({p!r}) returned False')",
208
+ " except Exception as exc:",
209
+ " ok_all = False",
210
+ " print(f'nltk.download({p!r}) raised {type(exc).__name__}: {exc}')",
211
+ "print('nltk_data_ok' if ok_all else 'nltk_data_partial')",
212
+ ].join("\n");
213
+ const code = await runProc(venvPython(), ["-c", pyCode], (line) => {
214
+ // Surface meaningful lines, skip generic nltk download chatter.
215
+ if (/^downloading|^nltk_data_|raised|returned False|nltk_missing/.test(line)) {
216
+ onProgress(`nltk: ${line}`);
217
+ }
218
+ });
219
+ if (code !== 0) {
220
+ onProgress(`(nltk check exited ${code} — Mode B vector RAG ingest may fail with "Resource 'punkt_tab' not found")`);
221
+ }
222
+ }
173
223
  export async function ensurePythonEnv(systemPython, expectedVersion, onProgress = (m) => console.log(chalk.gray(` [venv] ${m}`))) {
174
224
  if (venvIsValid(expectedVersion)) {
225
+ // Self-heal: ensure NLTK data is present even when the venv marker
226
+ // says we're up to date. This is what previously broke for boxes
227
+ // that upgraded the runner without invalidating the marker.
228
+ await ensureNltkData(onProgress);
175
229
  return { ok: true, pythonPath: venvPython() };
176
230
  }
177
231
  if (!existsSync(AGENTSCOPE)) {
@@ -240,6 +294,10 @@ export async function ensurePythonEnv(systemPython, expectedVersion, onProgress
240
294
  if (scrCode !== 0) {
241
295
  onProgress(`(scrapling install exited ${scrCode} — fast-path fetcher still works; stealth-rescue disabled)`);
242
296
  }
297
+ // NLTK tokenizer data — same idempotent check the always-runs path uses.
298
+ // Centralised in `ensureNltkData()` so the success/failure surface is
299
+ // identical whether the venv is fresh or already valid.
300
+ await ensureNltkData(onProgress);
243
301
  writeFileSync(VENV_MARK, venvMarkerValue(expectedVersion), "utf-8");
244
302
  // sanity: confirm shortuuid + agentscope (via PYTHONPATH) resolve now.
245
303
  // Probe must mirror the spawn env so PYTHONPATH=CACHE_DIR points at
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melaya/runner",
3
- "version": "1.0.41",
3
+ "version": "1.0.43",
4
4
  "description": "Run Melaya AI pipelines locally with your own LM Studio or Ollama models",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,