@melaya/runner 1.0.81 → 1.0.83
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/dist/connection.js +34 -0
- package/dist/pythonEnv.js +13 -5
- package/dist/sharedVendor.d.ts +7 -0
- package/dist/sharedVendor.js +16 -0
- package/package.json +1 -1
package/dist/connection.js
CHANGED
|
@@ -64,6 +64,30 @@ export async function connect(opts) {
|
|
|
64
64
|
console.log(chalk.yellow(` ⚠ Luma browser bridge failed to start: ${e?.message || e}`));
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
|
+
// Background warm-up of the assistant Python env, once per process, so the
|
|
68
|
+
// first assistant chat spawns near-instantly. No-op on a fresh runner (no
|
|
69
|
+
// shared bundle on disk yet) — the real assistant_start installs it then.
|
|
70
|
+
let _assistantPrewarmed = false;
|
|
71
|
+
const _prewarmAssistantEnv = async () => {
|
|
72
|
+
if (_assistantPrewarmed)
|
|
73
|
+
return;
|
|
74
|
+
_assistantPrewarmed = true;
|
|
75
|
+
try {
|
|
76
|
+
const { getLocalSharedVersion } = await import("./sharedVendor.js");
|
|
77
|
+
const localVersion = getLocalSharedVersion();
|
|
78
|
+
if (!localVersion)
|
|
79
|
+
return; // nothing cached yet — let assistant_start do it
|
|
80
|
+
const { ensurePythonEnv } = await import("./pythonEnv.js");
|
|
81
|
+
await ensurePythonEnv(opts.pythonPath, localVersion, (m) => { if (opts.verbose)
|
|
82
|
+
console.log(chalk.gray(` [assistant prewarm] ${m}`)); });
|
|
83
|
+
if (opts.verbose)
|
|
84
|
+
console.log(chalk.gray(" [assistant prewarm] ready"));
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
if (opts.verbose)
|
|
88
|
+
console.log(chalk.gray(` [assistant prewarm] skipped: ${e?.message || e}`));
|
|
89
|
+
}
|
|
90
|
+
};
|
|
67
91
|
socket.on("connect", async () => {
|
|
68
92
|
spinner.succeed(chalk.green("Connected to Melaya"));
|
|
69
93
|
// Report detected models
|
|
@@ -83,6 +107,12 @@ export async function connect(opts) {
|
|
|
83
107
|
// effort — failure here means Luma POSTs fall back to aiohttp
|
|
84
108
|
// (which 403s under the bot rule) but reads still work.
|
|
85
109
|
await _ensureLumaBridge();
|
|
110
|
+
// Pre-warm the assistant Python env in the BACKGROUND so the first chat
|
|
111
|
+
// message doesn't pay the venv check + one-time NLTK/cert self-heal inline
|
|
112
|
+
// (the biggest chunk of "◆ Assistant session … takes forever to spawn").
|
|
113
|
+
// We warm with the version already on disk so it hits the cache instead of
|
|
114
|
+
// reinstalling; skipped on a fresh runner (no bundle yet) to avoid churn.
|
|
115
|
+
void _prewarmAssistantEnv();
|
|
86
116
|
console.log(chalk.gray(" Waiting for pipeline runs...\n"));
|
|
87
117
|
});
|
|
88
118
|
socket.on("connect_error", (err) => {
|
|
@@ -315,6 +345,10 @@ export async function connect(opts) {
|
|
|
315
345
|
PYTHONUTF8: "1",
|
|
316
346
|
...sslEnv,
|
|
317
347
|
MEL_RUN_ID: payload.runId,
|
|
348
|
+
// Pipeline name so phone-driving runs can self-register as the phone's
|
|
349
|
+
// active run (arms the on-device working overlay + its Kill button)
|
|
350
|
+
// regardless of launch surface — desktop, native, or assistant.
|
|
351
|
+
MEL_PIPELINE_NAME: payload.pipelineName,
|
|
318
352
|
// Point agentscope hooks at the REAL server (not the browser's Vite URL).
|
|
319
353
|
// Convert wss://api.melaya.org → https://api.melaya.org so pushMessage,
|
|
320
354
|
// registerRun, and other agentscope HTTP calls reach the tRPC server.
|
package/dist/pythonEnv.js
CHANGED
|
@@ -320,13 +320,21 @@ async function ensureNltkData(onProgress) {
|
|
|
320
320
|
onProgress(`(nltk check exited ${code} — Mode B vector RAG ingest may fail with "Resource 'punkt_tab' not found")`);
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
|
+
// One-time-per-process guard for the cache-hit self-heal (NLTK + cert bundle).
|
|
324
|
+
let _selfHealedThisProcess = false;
|
|
323
325
|
export async function ensurePythonEnv(systemPython, expectedVersion, onProgress = (m) => console.log(chalk.gray(` [venv] ${m}`))) {
|
|
324
326
|
if (venvIsValid(expectedVersion)) {
|
|
325
|
-
// Self-heal: ensure NLTK data
|
|
326
|
-
// says we're up to date
|
|
327
|
-
// that upgraded the runner without invalidating the marker.
|
|
328
|
-
|
|
329
|
-
|
|
327
|
+
// Self-heal: ensure NLTK data + the cert bundle are present even when the
|
|
328
|
+
// venv marker says we're up to date (this is what previously broke for
|
|
329
|
+
// boxes that upgraded the runner without invalidating the marker). Both are
|
|
330
|
+
// stable for the process lifetime, so run them ONCE per runner process — the
|
|
331
|
+
// old code spawned two extra Python processes on EVERY assistant/pipeline
|
|
332
|
+
// start (~0.5-1.5s of pure latency on the assistant-spawn critical path).
|
|
333
|
+
if (!_selfHealedThisProcess) {
|
|
334
|
+
_selfHealedThisProcess = true;
|
|
335
|
+
await ensureNltkData(onProgress);
|
|
336
|
+
await _resolveAndCacheCertBundle(onProgress);
|
|
337
|
+
}
|
|
330
338
|
return { ok: true, pythonPath: venvPython() };
|
|
331
339
|
}
|
|
332
340
|
if (!existsSync(AGENTSCOPE)) {
|
package/dist/sharedVendor.d.ts
CHANGED
|
@@ -7,5 +7,12 @@
|
|
|
7
7
|
* runtime from the server's /api/v1/agents/shared-bundle endpoint,
|
|
8
8
|
* integrity-verified via SHA-256, and cached at ~/.melaya-runner/shared/.
|
|
9
9
|
*/
|
|
10
|
+
/**
|
|
11
|
+
* The shared-bundle version currently installed on disk (from shared-version.txt),
|
|
12
|
+
* or null if none/incomplete. Used to pre-warm the Python env on connect with the
|
|
13
|
+
* SAME version the cache already holds, so the warm-up hits the cache instead of
|
|
14
|
+
* triggering a reinstall.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getLocalSharedVersion(): string | null;
|
|
10
17
|
export declare function getSharedDir(): string;
|
|
11
18
|
export declare function ensureSharedModules(serverUrl: string, expectedVersion: string, runnerToken: string): Promise<void>;
|
package/dist/sharedVendor.js
CHANGED
|
@@ -14,6 +14,22 @@ import { createHash, createHmac, timingSafeEqual } from "crypto";
|
|
|
14
14
|
const CACHE_DIR = join(homedir(), ".melaya-runner");
|
|
15
15
|
const SHARED_DIR = join(CACHE_DIR, "shared");
|
|
16
16
|
const VERSION_FILE = join(CACHE_DIR, "shared-version.txt");
|
|
17
|
+
/**
|
|
18
|
+
* The shared-bundle version currently installed on disk (from shared-version.txt),
|
|
19
|
+
* or null if none/incomplete. Used to pre-warm the Python env on connect with the
|
|
20
|
+
* SAME version the cache already holds, so the warm-up hits the cache instead of
|
|
21
|
+
* triggering a reinstall.
|
|
22
|
+
*/
|
|
23
|
+
export function getLocalSharedVersion() {
|
|
24
|
+
try {
|
|
25
|
+
if (existsSync(VERSION_FILE) && cacheLooksValid()) {
|
|
26
|
+
const v = readFileSync(VERSION_FILE, "utf-8").trim();
|
|
27
|
+
return v || null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch { /* best-effort */ }
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
17
33
|
export function getSharedDir() {
|
|
18
34
|
// Return the CACHE_DIR root (not shared/ subdir) because the bundle
|
|
19
35
|
// now includes agentscope/ and crews/ alongside shared/. PYTHONPATH
|